1
2013-01-08 16:02:55.341 TodayApp[95470:14003] -[__NSCFBoolean objectForKey:]: unrecognized selector sent to instance 0x9b4964
2013-01-08 16:02:55.342 TodayApp[95470:14003] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFBoolean objectForKey:]: unrecognized selector sent to instance 0x9b4964'
*** First throw call stack:
(0x883012 0x20a2e7e 0x90e4bd 0x872bbc 0x87294e 0x7afc 0x234353f 0x2355014 0x23457d5 0x829af5 0x828f44 0x828e1b 0x2dcf7e3 0x2dcf668 0xfea65c 0x2679 0x2585)
libc++abi.dylib: terminate called throwing an exception

My app got almost 30 classes. I'm getting the above error when I enter a specific vc but only 1 time out of ten so there is no way for me to reproduce it. How can I debug this in an efficient way? Usually I "debug" using NSLog and step by step but I'm sure you can enlighten me with more efficient ways.

Update: I've added exceptions as suggested in the answers in this is the problematic line: NSString *card = [NSString stringWithFormat:@"%@-%@",[[UserAccount sharedInstance] cardNumber],[tokenData objectForKey:@"CardPhoneToken"]]; I'm still trying to figure out what is wrong with it.

Segev
  • 19,035
  • 12
  • 80
  • 152

3 Answers3

2

At first set an exception breakpoint. If so, it may not show any useful output at the moment the exception is thown. But you should see the very piece of your code, where it is thrown. That helps a lot. If you then press "continue execution" in the debugger, probably two or three times or so, eventually the error message comes up in the debug console. By then, the main function may be shown but by then you have seen already, where the origin of the exception was.

Ok, nownig that have a look at all objects that you are dealing with in that very line of code. One of these objects (or any property of these objects) is supposed to be an NSDictionary, because, as the error message tells you, an "objectForKey:" message has been send but no appropriate selector was found. That is because the object in question is of type Boolean/NSBoolean.

You have most probabyl assigned some numerical object or pointer to something that is supposed to be an NSDictionary. It may well be that you are accessing an uninitialized pointer which just happens to point to some boolean type of thing. In that case the error may be hard to reproduce.

However, doing so will guide you onto the right track.

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
  • I'm getting somewhere! ok, this is where it stops `NSString *card = [NSString stringWithFormat:@"%@-%@",[[UserAccount sharedInstance] cardNumber],[tokenData objectForKey:@"CardPhoneToken"]];` unfortunately no `NSNumber` or `NSDictionary` here. – Segev Jan 08 '13 at 14:49
  • Obvously `tokenData` is supposed to be an NSDictionary. At least it is sent the `objectForKey` selector to which it cannot respond. Just NSLog it in the line before. `NSLog(@"%@",tokenData);` and you may find out that it is an NSNumber or something alike. – Hermann Klecker Jan 08 '13 at 14:54
  • When ever you deal with core data - NSManagedObjects are dictionaries too. When ever you send a getter or setter (that is by assigning or retreiving values to or from properties) further below an NSDictionary is accessed. – Hermann Klecker Jan 08 '13 at 14:55
  • ` NSDictionary *tokenData = [[responseDict objectForKey:@"data"] objectForKey:@"multipass"] ; dispatch_async(dispatch_get_main_queue(), ^{ NSString *card = [NSString stringWithFormat:@"%@-%@",[[UserAccount sharedInstance] cardNumber],[tokenData objectForKey:@"CardPhoneToken"]];` .. `tokenData` is `NSDictionary` – Segev Jan 08 '13 at 14:56
  • I just NSLoged `tokenData`. Most of the times it returns a dictionary with items but when i get the error it returns 0. – Segev Jan 08 '13 at 15:01
  • No, tokenData is declared as NSDictionary. But I bet that the object indexed "multipass" in the dictionay-object indexd "data" in the responseDict is no NSDictionary. Try NSLog(@"%@",responseDict) and you wills ee the full structure of all the data. – Hermann Klecker Jan 08 '13 at 15:02
  • Fine, and 0 seems to be treated as a number and not nil. You could try dealing with hat. Don't know what the best approach is. Maybe you assign `[[responseDict objectForKey:@"data"] objectForKey:@"multipass"]` to some varialbe of type id first. Lets say you declared it `id unknownObject`. Next line: `unknownObject = [[responseDict objectForKey:@"data"] objectForKey:@"multipass"]`; Next line: `if (unknownObject isKindOfClass:[NSDictionary class]) ... `. Then it is save accessing its values by key. – Hermann Klecker Jan 08 '13 at 15:06
  • Not solved yet but you definitely gave me some leads. Thanks a lot! – Segev Jan 08 '13 at 15:07
0

Set up exception breakpoints for all exceptions on throw and on catch.

This can be done in the bottom right of the BreakPoint Navigator on the '+' sign. Add Exception Breakpoint... And select for Break: On Throw and create another one for On Catch

This should create a breakpoint that will help you identify where any exceptions are being generated.



A more cumbersome way is to create a dSYM-file and run an atos command.

This is done by archiving your project. Then in the Organizer right click the archive and show in finder. Then right click and show package content. Copy the TestApp.app.dSYM to a convenient location and navigate there in terminal.

Then type:

cd Contents/Resources/DWARF/

Then you can run the atos command:

atos -arch armv7 -o TestApp 0x7556fb0

Where TestApp is your app name and 0x7556fb0 is the address you want to investigate. In your case that could be 0x883012.

Sometimes that could give you a class and a line number of where the crash happened. Like:

[Class methodName:]; -211


Another way that seem to work sometimes is to set up your app for HockeyApp. This way you can send the crashreports to HockeyApp and there you sometimes get more detail information. It is helpful to also upload the dSYM file.

Roland Keesom
  • 8,180
  • 5
  • 45
  • 52
  • 1
    Perhaps you could ***explain*** why one might do such a thing, for the benefit of future visitors. – CodaFi Jan 08 '13 at 14:25
0

This exception should be easily debugged - search for all objectForKey: calls, and see where you can send this to boolean value.

Or, if you have too many lines of code with such call, you can symbolicate call stack: Symbolicating iPhone App Crash Reports

Community
  • 1
  • 1
Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48