Terminating app due to uncaught exception 'NSInvalidArgumentException - iphone

Ok here is an interesting one... I am receiving the
warning: Characters may not respond to 'addHeroType:atX:atY:fromMobTable'
although I have the functions defined properly as far as I can see so how about another pair of eyes?
Here is the definition in Characters.h
-(void) addHeroType:(int)newMobType atX:(int)x atY:(int)y fromMobTable:(Mobdefs*)newMobTable;
Here is the function in the Characters.m
-(void) addHeroType:(int)newMobType atX:(int)x atY:(int)y fromMobTable:(Mobdefs*)newMobTable
and here is the call I am making in another class call heroFactory (Characters.h is included in heroFactory):
[Characters addHeroType:1 atX:location.x atY:location.y fromMobTable:newMobTable];
But this line causes the app to terminate due to uncaught exception - checking the debugger I see "NSObject Does Not Recognize Selector"
I am convinced that the issue is the wierdness of why I am seeing a warning that the Character class may not respond to the function call as written even though it matches identically to the definition.
Any help greatly appreciated.

-(void) addHeroType:(int)newMobType atX:(int)x atY:(int)y fromMobTable:(Mobdefs*) newMobTable
That is declared as an instance method.
[Characters addHeroType:1 atX:location.x atY:location.y fromMobTable:newMobTable];
But you are calling it on the class as a class method.
So either, declare the method as a class method
+(void) addHeroType:(int)newMobType atX:(int)x atY:(int)y fromMobTable:(Mobdefs*) newMobTable
Or call it on an instance
Characters *instance = [[[Characters alloc] init] autorelease];
[instance addHeroType:1 atX:location.x atY:location.y fromMobTable:newMobTable];
Depending on the scope your method requires, of course.

Related

Objective-C property access: unrecognized selector sent to instance

I am new to objective-c, but coding for many years now. Somehow I don't get warm with Objective-C. I searched google and stackoverflow, but I think my problem is just to simple and stupid that no one has asked this yet.
My Code is based on DateSelectionTitles Example. http://developer.apple.com/library/ios/#samplecode/DateSectionTitles/Introduction/Intro.html
I have an NSManagedObject
#interface Event : NSManagedObject
#property (nonatomic, retain) NSDate * date;
...
// Cache
#property (nonatomic, retain) NSString * primitiveSectionIdentifier;
All prperties are defined in my datamodel, except the primitiveSectionIdentifier (as in the apple example)
But when I call
NSString *tmp = [self primitiveSectionIdentifier];
I get the Exception
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Event primitiveSectionIdentifier]: unrecognized selector sent to instance 0x74850c0'
To put it simple:
Event *foo = [[Event alloc] init];
if (foo.primitiveSectionIdentifier) {
NSLog(#"YEAH");
}
throws the same exception. So I basically want to check if primitiveSectionIdentifier is nil. But when I access the property, it throws an exception? Do I need to alloc each property before I can check if it has a value?!
Which of the Objective-C basics am I not getting here?
Thanks a lot for responses!
There is only one way how this can happen without compiler warnings - you must have written #dynamic primitiveSectionIdentifier; in your implementation file. This means that you don't want to define the method because you believe it is already defined somewhere else.
You are using a NSManagedObject, do you know how it works? You declare methods without implementation (putting #dynamic in the implementation) and when the method is called, it is not found and a special handler [NSObject doesNotRecognizeSelector:] is called instead. This handler checks the Core Data model whether an attribute for the given selector exists and if it doesn't, it throws the exception you are seeing.
So, the problem might the caused by the fact that primitiveSectionIdentifier is not declared in your model.
You are using an older example program, which uses a different style of memory management; if you are compiling under the iOS 5 or 6, that may be causing the problem.
Try
NSLog(#"primitiveSectionIdentifier = %#", self.primitiveSectionIdentifier);
If it doesn't give you the string you are looking for then the problem is likely in that the string object was never initialized and is still set to nil. In that situation, the code would compile, but sending a selector to a nil pointer would throw up an exception.

Objective C NSThread and anonymous function

Trying to use NSThread::detachNewThreadSelector with anonymous function
void (^testA)(void) = ^
{
NSAutoreleasePool *oPool = [[NSAutoreleasePool alloc] init];
NSLog(#"in threadA",nil);
[oPool release];
};
[NSThread detachNewThreadSelector:#selector(testA) toTarget:testA withObject:nil];
when I'm trying to run application I got error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSThread initWithTarget:selector:object:]: target does not implement selector (*** -[__NSGlobalBlock__ testA])'
can anyone give me a hand with that?
To use that NSThread API, you mist have an object and a selector. While a block is technically an object, it doesn't have any methods that you can invoke. As such, there's nothing you could pass in the action parameter that would make this work.
If you want to execute a block asynchronously, there are a couple ways you can do it:
Use Grand Central Dispatch's dispatch_async() function, or one of the appropriate variants.
Give the block to an NSBlockOperation, and hand that off to an NSOperationQueue.
Create a method on an object that takes a block parameter and simply executes it, and then pass that object and selector, along with the block, to the NSThread API. Don't forget to -copy the block first, or you'll probably crash.
It just does not work that way. A selector is the name of a method, and a block is not a method so you can't use a selector to call a block. If you want to execute a block in the background, you can use NSBlockOperation or dispatch_async().

How to find out if a method exists in Obj-C when given an NSString

I have a method as an NSString *. If it exists, I want to call it, and if not, do nothing.
SEL eventSelector = NSSelectorFromString(eventSelectorStr);
if ([delegate respondsToSelector:eventSelector]) {
[delegate performSelector:eventSelector];
[delegate adapterDidFinishAdRequest:self];
}
else {
// Does not implement selector
}
This code does not work, since NSSelectorFromString will register the string as a selector, so respondsToSelector:eventSelector will cause a crash because the selector is actually invalid.
Why do you say that that doesn't work? This is the most common way to implement invoking optional delegate methods. I've never had an issue with that construct not working.
Let's clear up some confusion.
NSSelectorFromString() will generate a valid selector from the string, and will not crash in doing so. respondsToSelector: will validly determine if the delegate implements that method or not, without crashing. It is true that if you call performSelector: with a selector that the delegate doesn't implement it will cause a crash.
However, that isn't the situation here. The code is valid. If you have a crash in this code, I would check the error message and look instead to adapterDidFinishAdRequest:.
Try checking for eventSelector != nil before using it.
It took me a while to understand this as well. The key insights are that a selector reference is basically just a dressed-up C string, and that it doesn't 'belong' to any particular class or object. When the NSSelectorFromString() documentation says that the selector is 'registered', it just means that a dressed-up C string is 'blessed' (my term) for use as a selector within the Objective-C runtime.
Here's the section on the return value for NSSelectorFromString() from Apple's documentation:
Return Value
The selector named by aSelectorName.
If aSelectorName is nil, or cannot
be converted to UTF-8 (this should be
only due to insufficient memory),
returns (SEL)0.
Reading it carefully shows that the only situations which can cause (SEL)0 to be returned are if your string was nil or if you ran out of memory.

Cocoa touch - problem with button-viewController connection

I'm very new to cocoa touch and am stuck on a problem that doesn't seem to have a google solution. I have added a view to my application, and this view has a button on it. When the button is pressed I want the callback to perform an operation.
My problem is that the callback isn't being called. I created the view in Interface Builder, connected the touch-up-inside connection to my Owner class (in this case a viewController class), and selected the appropriate callback.
The error I get is as follows:
2009-10-13 17:13:51.708 MyApp[7467:20b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSCFSet contactsButtonPressed:]: unrecognized selector sent to instance 0x4c27330'
As I understand it this suggests that the connection between contactsButtonPressed and MyViewController is wrong. I'm not sure where the NSCFSet object comes from.
Does anyone have any idea?
Thanks!
The error I get is as follows:
2009-10-13 17:13:51.708 MyApp[7467:20b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSCFSet contactsButtonPressed:]: unrecognized selector sent to instance 0x4c27330'
You're probably under-retaining whatever controller object of yours is supposed to receive that action message. Add an NSLog call in the controller's dealloc method; you'll probably find that it gets deallocked before you expect it to.
The question to ask then is what should own that controller. Then, make sure that all of the owners are retaining it.
If you're holding the controller in a property, make sure that you actually use that property. A common mistake is to write myController = theController, which bypasses the property and assigns directly to the instance variable, instead of self.myController = theController (property access syntax, implicit accessor message) or [self setMyController:theController] (explicit message syntax).
Also, if you've implemented your own accessors for the property (especially setMyController:), make sure your setter releases the old object and retains the new one. Of course, this is assuming you have a reason to implement your own accessor; normally, you should simply #synthesize the property and let the compiler write the accessor for you.
somewhere in your code you have a line that looks like this:
[button addTarget:self action:#selector(contactsButtonPressed:)];
If you have a line that looks like this, you will also need to have a method with this signature:
- (void)contactsButtonPressed:(UIButton *)sender {
...
}
If you look at the error, it seems that you are sending the message to an NSCFSet object instead of the controller. I would check that you are setting delegate to self or the controller.
I'm new to cocoa too,
Maybe you forgot to add the sender parameter to your contactsButtonPressed.
Is your view's class named NSCFSet?
Try pasting some code.

How to reference property of static library

I'm referencing another project's target static library. I successfully followed instructions from this site. Below is the project using a class named FileIO from the library.
I create a FileIO object and assign a string to its name property. Then I get a __TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__ on the assignment of name.
In applicationDidFinishLaunching I do this:
fileObj = [[FileIO alloc] init];
fileObj.name = #"test";
and this is in the .h file:
#class FileIO;
#interface Nav1AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
FileIO *fileObj;
}
In the library, FileIO is a simple class with name in it. I have also tried [fileObj setName:#"test"] but get the same results. Here's the stack trace:
2009-04-01 20:37:17.721 NavNew[81425:20b] *** -[FileIO setName:]: unrecognized selector sent to instance 0x5219b0
2009-04-01 20:37:17.723 NavNew[81425:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[FileIO setName:]: unrecognized selector sent to instance 0x5219b0'
2009-04-01 20:37:17.724 NavNew[81425:20b] Stack: (
2454561035,
2461146683,
2454590218,
2454583564,
2454583762,
11275,
816111650,
816149355,
2455110190,
2454063909,
2454064344,
827745792,
827745989,
816114848,
816160924,
11128,
10982
)
(gdb)
I have discovered this is a problem only with instance members (property or method). Static methods work fine. I also opened the library .a file in the hosting project. I don't see the instance property anywhere in it.
Any suggestions on what I'm doing wrong?
In the instructions you used to "import" the static library, the author describes several cases of strange errors occurring somewhat randomly, which is why I'd suggest a different approach: using an Xcode cross-project reference and shared build output directory. Here's a link to a tutorial with screenshots: http://www.clintharris.net/2009/iphone-app-shared-libraries/
I've been using this strategy for several months with multiple projects and static libraries--it's been great and I haven't experienced any problems. The other really nice perk is that you use an Xcode environment variable to reference the project with the static library (including the header files); this makes the solution really flexible if you have multiple developers working on the same project, need to move directories around, etc.
For some reason, the FileIO object that you have doesn't respond to the setName: message, so it's throwing an NSInvalidArgumentException when you try to send that message. My best guess is that the shared library isn't being loaded properly for some reason, so the implementation of setName: isn't getting loaded, so the runtime gets confused and thinks that setName: isn't implemented.
I'm not sure how to go about fixing this, but it does appear that the [[FileIO alloc] init] is succeeding (or at least to the point of not throwing an exception), so something is working at least. To get the list of messages that are allowed, you can try the following:
unsigned int methodCount;
Method *methods = class_copyMethodList(object_getClass(fileObj), &methodCount);
for(unsigned int i = 0; i < methodCount; i++)
NSLog(#"Method %u: %s", i, sel_getName(method_getName(methods[i])));
free(methods);
For information on the various Objective-C runtime methods, see the Objective-C 2.0 Runtime Reference.