Tracking Through iPhone Source

There are many better ways to trace through your code in any environment than with print statements.  If there’s not, you need to change jobs (or convince them to choose an environment that won’t waste all your time chasing bugs).

Your first order of business should be to familiarize yourself with your debugger.

However, there are times that you want to track through the code without having to break.  Watching what is going on in some event code is a good example.

You may often want to print out what method you are executing when in Cocoa Touch (or plain Cocoa for that matter).  If you are new to the iPhone and/or Objective-C you may not be aware of the two “silent arguments” that get sent to every message that dispatched in the Objective-C runtime.

You can think of the methods as C functions that receive all the arguments you see in the Objective-C code, plus two others.  The first is self, which you should be familiar with.  You may have thought it was a language keyword with supernatural powers.  In reality, it is the first argument to your method.  It’s always named self, and it’s of type id – i.e. it can be any kind of object.

The other is a selector, which is type SEL. It is named _cmd, and just like self you can use it anytime you’re inside a method. Though the preceding underscore should give you a hint that it’s use is expected only in uncommon circumstances.

All this is a long walk back to the point. If you want to print this information out, rather that retyping every method name, and mistyping them, and not changing them when the names change, and copy-paste-erroring all over the place, you can have cleaner and more maintainable code using the _cmd value.

A SEL is not an object, it is an opaque type. So we’ll need to convert it into something we can print. There’s a nice “function” defined for that.

Some example uses:

NSLog(@"[%@ %@]", [self className], NSStringFromSelector(_cmd));
NSLog(@"%s: [%@ %@]", __FILE__, [self className], NSStringFromSelector(_cmd));
NSLog(@"%s %d: [%@ %@]", __FILE__, __LINE__, [self className], NSStringFromSelector(_cmd));

Of course the first example won’t tell you what file it’s in. You may have a subclass instance running through a superclass’ code. If you really want to know the file or the line number, the later examples show you how to take advantage of the C precompiler values to do that.

There are a variety of other uses for selectors. Objective-C’s dynamic dispatching can allow some very powerful behaviors with them. But that’s for another day.

Note: [object className] is not defined in the iPhone on-board library.  You’ll have to replace the [self className] with NSStringFromClass([self class]) for it to run natively on the iPhone OS.