Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MythicFrost

macrumors 68040
Original poster
Mar 11, 2009
3,944
40
Australia
Hi,

I'm trying to add a button to my MainWindow programatically, but it isn't working... could anyone have a look at the code for me and point out my mistake? The error is "[NSView addButtonWithTitle:]: unrecognised selector sent to instance xxx".

TestAppDelegate.h:
Code:
#import <Cocoa/Cocoa.h>

@interface TestAppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
	NSButton *bExit;
}

@property (assign) IBOutlet NSWindow *window;
@property (nonatomic, retain) NSButton *bExit;

- (void)bExit_click;

@end
TestAppDelegate.m
Code:
#import "TestAppDelegate.h"

@implementation TestAppDelegate

@synthesize window, bExit;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	// Insert code here to initialize your application
	NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
	//NSLog(@"test");
	bExit = [[window contentView] addButtonWithTitle:@"Exit"];
        //Previously I was doing bExit = [NSButton alloc]; [bExit init]; and then adding it to the contentView via addObject... that wasn't working either.

	[[window contentView] enterFullScreenMode:screen withOptions:nil];
}

- (void)bExit_click {
	[[window contentView] exitFullScreenModeWithOptions:nil];
}

@end

Kind Regards
 
A "selector" is the message that is sent to the object. In this case, "addButtonWithTitle:" is the selector. If the object does not have a method that matches that selector, it will "not recognize" it. Look at the documentation for NSView to make sure it defines such a method.
 
A selector error message also occurs if a message is being sent to an object that doesn't exist or visa versa (IE, you forgot to alloc and init something) OR you forgot to put a @selector(method) directive somewhere.
 
Do you get any warnings when you compile? Like "this object bla bla bla might not recognise this selector? "
 
A selector error message also occurs if a message is being sent to an object that doesn't exist or visa versa (IE, you forgot to alloc and init something) OR you forgot to put a @selector(method) directive somewhere.

I don't think this is true, namely that an uninitialized (or allocated) object pointer would ever give "unrecognised selector sent to instance xxx" error.

I have tried to recreate this, and if you have any code that would do so please post it.

Sending a message to some random place in memory is much much more likely to result in "EXC_BAD_ACCESS" error.

For example:
Code:
SomeClass1 *object = [SomeClass1 someConvenienceMethod];
SomeClass2 *object2 = object+1; // gives some weird part in memory
[object2 anyMethod];  // would give "EXEC_BAD_ACCESS"  most, if not all, of the time
Every time I create a pointer, but don't assign anything to it, it is already nil. I don't know if this is defined behavior, but it won't give any "unrecognised selector sent to instance xxx".

Code:
SomeClass1 *object;
[object anyMethod]; // doesn't do anything.
This maybe undefined, but if anything I'd expect segfault or EXEC_BAD_ACCESS.



To sum it up, I've always found "unrecognised selector sent to " errors to be the easiest ones to troubleshoot.
It is easy to search your code for the method and try to think or reasons why the object you're using it on doesn't respond to it.
Examples...
*Object returned from another method isn't of the class you think they are.
*Trying to use a method on a collection class, like NSArray or NSDictionary without first getting the object out of them
*Typos that you didn't catch, or that Xcode's method-name auto-fill put in the wrong one and you didn't notice.
 
I don't think this is true, namely that an uninitialized (or allocated) object pointer would ever give "unrecognised selector sent to instance xxx" error.

For me, the most common occurrence of this error is from a dangling pointer, which is usually because I failed to properly retain the object (the pointer was reassigned to something else). The worst part about these errors is that they are silent outside the console: your app will start behaving erratically, but not actually fault or crash.
 
For me, the most common occurrence of this error is from a dangling pointer, which is usually because I failed to properly retain the object (the pointer was reassigned to something else). The worst part about these errors is that they are silent outside the console: your app will start behaving erratically, but not actually fault or crash.

Can you give an example? "reassigned to something else"?? Something else that doesn't respond to the same methods? I can't think of any ways for this to happen off the top of my head that aren't odd polymorphism for the sake of polymorphism.

Also every time I think I've ever gotten the unrecognized selector sent to instance error it has been an exception and halted the program.
 
Can you give an example? "reassigned to something else"?? Something else that doesn't respond to the same methods? I can't think of any ways for this to happen off the top of my head that aren't odd polymorphism for the sake of polymorphism.

The memory gets freed, and a new object is allocated at the same address as the old one used to be at. Happens semi-often.
 
Hi,

I got no warnings when compiling, but no code is executed after the line that causes the error, it seems to be when I try to add the button as a child of the window's view.
 
Can you give an example? "reassigned to something else"?? Something else that doesn't respond to the same methods? I can't think of any ways for this to happen off the top of my head that aren't odd polymorphism for the sake of polymorphism.

Also every time I think I've ever gotten the unrecognized selector sent to instance error it has been an exception and halted the program.

It works like this:

You have a pointer to an object that resides in a memory block. That memory block sits on top of a non-transient (retained) block. Some process releases your object, freeing its block. The next allocation that will fit in that space is then assigned to that pointer, so the pointer gets reused. Your process believes the original object still resides in that block, so it sends a message which is received by a different object. If you are unbelievably unlucky, the replacement object will recognize and respond to the selector, probably yielding an undesirable result. Otherwise you will get an error.

In my experience (perhaps because of my build flags?), the main runloop, or at least parts of it, seems to be a big try/catch where the catch for unrecognized selector just writes to the console and continues with the runloop, leaving the app's context in a faulty state. Hence, erratic behavior.
 
Hi,

I got no warnings when compiling, but no code is executed after the line that causes the error, it seems to be when I try to add the button as a child of the window's view.

If you are still using -addButtonWithTitle:, the line will continue to fail. NSView does not define a method with that selector. Read the docs.
 
It works like this:

You have a pointer to an object that resides in a memory block. That memory block sits on top of a non-transient (retained) block. Some process releases your object, freeing its block. The next allocation that will fit in that space is then assigned to that pointer, so the pointer gets reused. Your process believes the original object still resides in that block, so it sends a message which is received by a different object.

Note that the original poster wrote code like this at some point:

Code:
someobject = [Class alloc];
[someobject init];
instead of

Code:
someobject = [[Class alloc] init];
It can happen that the init method decides that it cannot initialise the object as intended, and therefore releases "self" and returns nil. Another possibility is a singleton Class, where only one object of that class is supposed to exist, and every call to "init" except the first one will deallocate its "self" and return the singleton object. In both cases what you described could happen very easily.
 
If you are still using -addButtonWithTitle:, the line will continue to fail. NSView does not define a method with that selector. Read the docs.
How come it showed/auto filled such a selector? I didn't type it manually, I was looking for the solution and that was an option.
It can happen that the init method decides that it cannot initialise the object as intended, and therefore releases "self" and returns nil. Another possibility is a singleton Class, where only one object of that class is supposed to exist, and every call to "init" except the first one will deallocate its "self" and return the singleton object. In both cases what you described could happen very easily.
I wrote the code like that because, at the time, [[Class alloc] init]; wouldn't show up as an option, I had to do them separately. However, for some reason its working now...
Code:
#import "TestAppDelegate.h"

@implementation TestAppDelegate

@synthesize window, bExit;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	// Insert code here to initialize your application
	
	
	
	//NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
	NSLog(@"test");
	 
	bExit = [[NSButton alloc] init];
	[bExit setTitle:@"Exit"];
	[[window contentView] addObject:bExit];

	//[[window contentView] enterFullScreenMode:screen withOptions:nil];
}

- (void)bExit_click {
	[[window contentView] exitFullScreenModeWithOptions:nil];
}

@end

I never see the button on my window? Any thoughts?

Kind Regards
 
Stop trusting autocompletion and start reading the documentation.

Xcode doesn't always recognize the type of the receiver and sometimes shows completions for unsupported methods.
 
My new code: I get no errors, but it still doesn't show up. Is [[window contentView] what I should be adding them too?
Code:
	bExit = [[NSButton alloc] init];
	NSRect rRect = NSMakeRect(100, 100, 100, 20);
	[bExit setBounds:rRect];
	[bExit setTitle:@"Exit"];
	[[window contentView] addSubview:bExit];
Stop trusting autocompletion and start reading the documentation.

Xcode doesn't always recognize the type of the receiver and sometimes shows completions for unsupported methods.
Erm ok ty, I didn't know.
- addObject: instead of - addSubview: ??

Do you need to give your NSButton a position/size??
OK updated with that info above
 
Thank you! That got it working :)

Does anyone know how I'd add a selector to bExit to run bExit_click when clicked? I have looked through the documentation and couldn't find anything (and I'm still looking).

Kind Regards
 
It sounds like you might benefit from a good book on Cocoa programming. Aaron Hillegass and Steve Kochan have each written books that are highly regarded on this forum.
 
Thanks for your reply,

(Look up NSButton to find out how it works and how to set it up and use it.)
As I said, I was looking through the documentation. Although, I did find the link you were referring to, and it is more helpful than browsing through the list of APIs or whatever they are. And I did manage to find what I was looking for.
Groping around like a blind person is an very ineffective way to learn Mac programming (or at least very inefficient). Or you could put a few shekels in, say, Aaron Hillegass' or Steve Kochan's pocket and use a good book to take a deliberate approach to learning what you are doing.
I'm not uh groping around for anything, I'm looking around for this stuff in the documentation, but as usual, I have both trouble finding it, and sometimes understanding it when I do find it. As an added plus, I post a thread as well, since someone will often be able to reply with the answer significantly quicker than I can find it, as well as potentially offer more insight on what I'm doing.
 
Does anyone know how I'd add a selector to bExit to run bExit_click when clicked? I have looked through the documentation and couldn't find anything (and I'm still looking).

Don't forget to check out the documentation for a class's superclass. For example NSButton inherits from NSControl.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.