views:

3051

answers:

6

I am a long time Microsoft developer and I am new to iPhone development using XCode. So, I am reading a book and going through examples trying to teach myself how to write an iPhone application using Objective-C. All has been good so far, however, once in a while I run into the generic 'objc_exception_throw' message at runtime. When this happens, the source of this exception is very difficult to find. After some trial and error I found my answer. One of the parameters was misspelled.

As you can see below, I misspelled the 'otherButtonTitles' parameter by leaving out the second 't' in button.

UIAlertView *alert = [[UIAlertView alloc] 
       initWithTitle:@"Date and Time Selected" 
       message:message 
       delegate:nil
       cancelButtonTitle:@"Cancel"
       otherButonTitles:nil];

The reason this took me time to find is that the code built successfully. Is this normal behavior for the Objective-C compiler? I am used to having the build fail in the .NET compiler when I make a common syntax error like this. Is there a compiler setting I can change to make the built fail when I make these mistakes?

+8  A: 

Misspelled parameters should generally result in a "Warning: such-and-such object does not respond to selector x" in yellow at the line in question. I believe this is on by default, as I didn't have to change any compiler settings to see these.

Also, when I encounter an uncaught exception, it's sometimes beneficial to drop into the gdb console (should come up when you execute your app) and type the following to get backtraces for all threads:

t a a bt

drewh
"t a a bt" is an abbreviation for "thread apply all backtrace" and simply prints a backtrace for all threads
Frank Szczerba
A: 

This is (a maddening) part of the Objective-C language - it's not considered an error if a class can't respond to a message. The message instead wends its way back up the call stack until it falls off the top...

edoloughlin
+1  A: 

The reason it's not a compilation error, is because it's perfectly valid to send a message not known at compile time to any object (and any object can be configured to handle messages dynamically as well). All method calls are really messages being sent to objects.

In general, if you see any warnings you should address them, as in most cases they can lead to problems (as you saw). The misleading aspect is here is that if you compile a file once and it has only warnings, if you compile other classes without making changes to the class that has warnings, the warning will not show in the compiler messages. So every now and then you may want to "clean all targets" and build again to make sure you didn't miss any warnings.

Kendall Helmstetter Gelner
+1  A: 

What you did is not a compile-time error, because the Objective-C runtime checks at runtime if an object can respond to the message you send to it.

I recommend adding this build setting to your target or project:

GCC_TREAT_WARNINGS_AS_ERRORS = YES
Chris Lundie
+6  A: 

Always use the -Werror GCC setting (GCC_TREAT_WARNINGS_AS_ERRORS = YES). You should never have warnings in your code and this is an example where the warning is a critical error.

Also, if you get an objc_exception_throw, switch to the console (Command-shift-R) and look for the first "low" number address.

2009-04-01 13:25:43.385 CrashExample[41720:20b] Stack: (
    2528013804,
    2478503148,
    2528036920,
    2528053460,
    2358032430,
    11076,
    11880,
    816174880,
    345098340,
    145973440,
    816174880,
)

In this case it would be "11076". So type in the console:

info line *11076

That will tell you the line in your code where the exception was thrown.

Matt Gallagher
That's some great advice - one other thing to add is to set a global breakpoint on "objc_exception_throw", which will automatically break when your code does something that throws an exception.
Kendall Helmstetter Gelner
+18  A: 
lhunath
NOTE: In order to have the "GCC 4.0 Warnings" section appear in your settings (as shown above) you must have the Base SDK and the Active SDK set to the Device and not the Simulator.
rtemp
Also, when you enable "Treat Warnings as Errors" you will still see the warnings as before but you will get 1 somewhat misleading error "Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.0 failed with exit code 1". This error will go away when all warnings are cleared.
rtemp