Programmatically attaching event handlers - objective-c

So, I'm trying to programmatically attach event handlers to widgets I've placed on my iphone application using:
addTarget:action:forControlEvents
I have added a UISegmentedControl in Interface Builder which is exposed through #property seg and in loadView, I have:
- (void)loadView
{
[ super loadView ] ;
//k after that attach our own event handlers
[ seg addTarget:seg action:#selector(sliderEventIB) forControlEvents:UIControlEventAllEvents ];
}
sliderEventIB, just tells us it feels the event:
-(IBAction)sliderEventIB:(id)sender forEvent:(UIEvent*)event
{
puts( "I feel you joanna" ) ;
}
but the error I'm getting is
ViewControllersTest[6744:207] *** -[UISegmentedControl sliderEventIB]:
unrecognized selector sent to instance 0x3b21b30
Any idea what it doesn't like here?

It seems like you just forgot to insert the colon in addTarget:
[ seg addTarget:seg action:#selector(sliderEventIB:) forControlEvents:UIControlEventAllEvents ];
It should be sliderEventIB: not sliderEventIB.

The proper code is as such:
- (void)loadView
{
[super loadView];
[seg addTarget:self action:#selector(sliderEventIB:forEvent:) forControlEvents:UIControlEventAllEvents];
}
- (IBAction)sliderEventIB:(id)sender forEvent:(UIEvent*)event
{
NSLog(#"I feel you joanna");
}
Notice that the method has the same selector as is registered using addTarget:action:forControlEvents.

Well, the UISegmentedControl doesn't have the 'sliderEventIB' method.
The 'addTarget' section of the method asks: "who do I inform once an event occurs?". In this case, you specified that the UISegmentedControl should be informed and it should call sliderEventIB on that object. Instead, you should say
[seg addTarget:self action:#selector(sliderEventIB) forControlEvents: UIControlEventAllEvents]

Related

[NSImage setHidden:]: unrecognized selector sent to instance

macOS Xcode Objective-C. Very new, so bear with me.
Displaying an image programmatically using:
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
m_imgBack = nil;
}
- (void)drawRect:(NSRect)rect {
rect = [ self bounds ];
if( m_imgBack )
[m_imgBack drawInRect:NSMakeRect(0,0,rect.size.width,rect.size.height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}
- (void)InitControls {
LoadImageFromFile( [ NSString stringWithFormat:#"%#/common/background.png", DATA_PATHNAME ], &m_imgBack );
}
This draws the background.png without a problem. However, I can not see to hide it using:
[m_imgBack setHidden:YES];
It just kicks back error: [NSImage setHidden:]: unrecognized selector sent to instance. I thought you could sethidden on an NSImage?
You can think of NSImage as a data object, so hiding it doesn't make sense just like hiding an NSArray or NSDictionary doesn't make sense.
If you're displaying the image in a view, the view can be hidden using isHidden. It's not clear from the code snippet what class the code belongs to, but assuming it's a subclass of NSView, you could try [self setHidden:YES].

Cocoa NSOpenGLView - [win setDelegate:view ] shows error. How to delegate manually?

I'm programming in Eclipse (not Xcode) on Yosemita 10.10...
I try to catch MouseMoved event, but it not called (mouseDown, mouseDragged - works fine). So I'm using this example code from here
http://lists.apple.com/archives/mac-opengl/2003/Feb/msg00069.html
but compiller show error on
[app setDelegate: view];
(- cannot initialize a parameter of type 'id' with an lvalue of type 'NSView *')
If I comment this line - it's work, but mouseMoved don't calling.
Please help! I'm newbie in objective-c
OS X does not automatically track the mouse movement events for you unless you request them.
In order to receive mouseMoved: events, you should add an NSTrackingArea to your subclass of NSOpenGLView. For example:
- (void)awakeFromNib {
NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.frame options:NSTrackingActiveAlways|NSTrackingMouseMoved owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
After that, your mouseMoved: method will be called.
- (void)mouseMoved:(NSEvent *)theEvent {
NSLog(#"moved");
}
You can optionally implement updateTrackingAreas if you need to update your tracking area manually when the view resizes. For details, please refer to Using Tracking-Area Objects.

UIImageView setImage not working in a delegate method?

I have a problem calling the setImage function in the opencv delegate method processImage.
When I call setImage in viewDidLoad, I can see the image, but when I do the same in processImage, it doesn't work.
What's the problem here?
- (void)viewDidLoad
{
[super viewDidLoad];
// This works !
[processImageView setImage:[UIImage imageNamed:#"resistor3.jpg"]];
}
- (void)processImage:(cv::Mat&)img {
// This does not work anymore !
[processImageView setImage:[UIImage imageNamed:#"resistor3.jpg"]];
}
When you modify the UI you must do it from the main thread, chances are that the delegate method, if it's being called, is called on another thread. Try this.
- (void)processImage:(cv::Mat&)img {
dispatch_async(dispatch_get_main_queue(), ^{
[processImageView setImage:[UIImage imageNamed:#"resistor3.jpg"]];
// I also think you should use the dot syntax, but that's purely a style thing
// processImageView.image = [UIImage imageNamed:#"resistor3.jpg"];
});
}
EDIT: Add recommendation about using dot syntax

UINavigationBar topItem/items seems to double-pop on back

I am managing my own UINavigationBar. I need to do this due to extensive skinning. The documentation for UINavigationController warns that there are limitations to skinning the UINavigationBar when used with a UINavigationController.
I have put in extensive logging and from everything I can tell, pushing the "Back" button in the UINavigationController pops two items off of of the stack instead of one. I get a single delegate callback telling me that it is removing the logical item, but it actually removes that one and one more.
The item added to the UINavigationController in awakeFromNib should never be removed. It is being removed for some reason.
There are two similar questions, but neither have satisfactory answers. The two questions are:
UINavigationBar .items accessor doesn't return the current UINavigationItem
UINavigationBar seems to pop 2 items off stack on "back"
- (void)awakeFromNib {
[headerView setDelegate: self];
[headerView pushNavigationItem: tableDisplay animated: NO];
}
- (void) selectedStory: (NSNotification *)not {
[headerView pushNavigationItem: base animated: NO];
NSLog(#"Selected story: %#", base);
}
- (void) baseNav {
NSLog(#"Current items: %#", [headerView items]);
BaseInnerItem *current = (BaseInnerItem *)[headerView topItem];
[self addSubview: [current view]];
}
- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPushItem: (UINavigationItem *)item {
return YES;
}
- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPopItem: (UINavigationItem *)item {
return YES;
}
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item {
NSLog(#"didPushItem: %#", item);
[self baseNav];
}
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item {
NSLog(#"didPopItem: %#", item);
[self baseNav];
}
Edited to add relevant debugging from a single run:
2010-10-13 02:12:45.911 Remix2[17037:207] didPushItem: <TableDisplay: 0x5d41cc0>
2010-10-13 02:12:45.912 Remix2[17037:207] Current items: (
"<TableDisplay: 0x5d41cc0>"
)
2010-10-13 02:12:49.020 Remix2[17037:207] didPushItem: <WebDisplay: 0x591a590>
2010-10-13 02:12:49.021 Remix2[17037:207] Current items: (
"<TableDisplay: 0x5d41cc0>",
"<WebDisplay: 0x591a590>"
)
2010-10-13 02:12:49.023 Remix2[17037:207] Selected story: <WebDisplay: 0x591a590>
2010-10-13 02:12:59.498 Remix2[17037:207] didPopItem: <WebDisplay: 0x591a590>
2010-10-13 02:12:59.499 Remix2[17037:207] Current items: (
)
You always have to call [super awakeFromNib] when your subclass implements that method, per the documentation for -awakeFromNib:
You must call the super implementation of awakeFromNib to give parent classes the opportunity to perform any additional initialization they require
Importantly, however, ...
I don't understand why you have to actually manage your own navigation bar. If you subclass UINavigationBar and only override certain drawing or layout methods such as -drawRect:, -layoutSubviews, etc., then all of the logic behind managing the navigation bar in a navigation controller will just fall back on the original UINaviationBar class.
I've had to do extensive view customization for almost every major UIKit class, but I always left the complicated logic to the original classes, overriding only drawing methods to customize the look and feel.
Incidentally, it's actually much easier to skin an entire app without subclassing at all if all you're doing is using custom image assets. By setting a layer's contents property, you can either customize the look and feel of a UIView-based class on an as-needed basis or throughout your entire app:
#import <QuartzCore/QuartzCore.h>
...
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage * navigationBarContents = [UIImage imageNamed:#"navigation-bar"];
self.navigationController.navigationBar.layer.contents =
(id)navigationBarContents.CGImage;
}
You can set the contents for any class that inherits from UIView: navigation bars, toolbars, buttons, etc. It's a lot easier to manage this way without having to subclass at all.
This appears to be a bug in the implementation of -[UINavigationBar items]
When called from inside the -navigationBar:didPopItem: delegate method, it will omit the last object. You can check this by calling [navigationBar valueForKey:#"_itemStack"] to retrieve the underlying array and see that the expected items are still there.
Adding a dispatch_async inside -navigationBar:didPopItem:method successfully works around the issue in my app.

Updating UI Elements with Controller Constructor

I have an NSSlider (slider) and an NSLabel (label) on a window. I also have a class "Controller" that updates the label whenever the slider's value is changed.
The default position of the slider is 0.5, I'm trying to get is where Controller's constructor updates the label upon program launch.
The following is the implementation file for my attempt to do this. Everything works fine except the label is always 0 when I start the program.
#implementation Controller
{
}
-(id)init
{
NSLog(#"initializing...");
[self updateLabel];
return self;
}
- (IBAction)sliderChanged:(id)sender
{
[self updateLabel];
}
- (void)updateLabel
{
label.text = [NSString stringWithFormat:#"%.1f", slider.value];
}
#end
In the console I see the text "initializing...", but the label is never updated. What am I missing?
The controller may be getting initialized (where is your call to [super init]?), but that doesn't mean the outlets are hooked up. The proper way to do that would be to rely on a viewDidLoad, windowDidLoad, or awakeFromNib method.
you should achieve this with bindings and without any "glue code" in controllers.
Here's some reference on how to use them: http://cocoadevcentral.com/articles/000080.php