debugging objective-c in xcode for iOS

November 02, 2011

I’m coding again in native Objective-C coding for iOS with the lovely XCode. It has been a while so I’ve been reading up on debugging tricks. Sadly, it still feels a bit like debugging in Macsbug in 1990…

The graphical display of object values is fairly useless, but in gdb, we can use the po command to get a pretty printing of the object if it comes with a built in description (for details see nice writeup from cocoa with love).

For our own objects, we can define a debugDescription method. For example, if I have a Thing class which is a subclass of NSObject and just has a title and subtitle:

@implementation Thing

@synthesize title;
@synthesize subtitle;

- (NSString *)debugDescription { return [NSString stringWithFormat:@"title: %@n subtitle: %@", title, subtitle]; }

@end

Then if I find myself at a breakpoint with an instance of Thing in scope, called “thing”:

(gdb) po thing
title: Another
subtitle: Another example

Or if I have an array of Thing instances, called “things”:

(gdb) po things
<__NSArrayM 0x6a157a0>(
title: Basic
subtitle: My Thing,
title: Something
subtitle: Example of something,
title: Another
subtitle: Another example
)

iphonedevelopertips illustrates this nicely in more detail with the description method which will do the same thing for any subclass of NSObject.

Note: print-object actually calls the debugDescription method of the specified object. NSObject implements this method by calling through to the description method. Thus, by default, an object’s debug description is the same as its description. However, you can override debugDescription if you want to decouple these; many Cocoa objects do this. (via Apple Tech Note 2124)

Update: LLVM Debugger sucks less

If you choose the LLVM Debugger, instead of gdb, you can see properties on an object without defining a description or debugDescription method:


(lldb) po thing
(Thing *) $8 = 0x06a487d0 
(lldb) po thing.title
(NSString *) $9 = 0x00005984 Another
(lldb) po thing.subtitle
(NSString *) $10 = 0x00005994 Another example

…but still no love for Arrays:


(lldb) po things
(NSMutableArray *) $11 = 0x06a0b6a0 (
,
,

)

…just for fun, let’s see how to look at a property of the first object in an array:


(lldb) po [things objectAtIndex:0]
(id) $12 = 0x06a44d20 
(lldb) po [things objectAtIndex:0].title
error: warning: instance method '-objectAtIndex:' not found (return type defaults to 'id')
error: property 'title' not found on object of type 'id'
error: 1 errors parsing expression
(lldb) po (Thing*)[things objectAtIndex:0].title
error: warning: instance method '-objectAtIndex:' not found (return type defaults to 'id')
error: property 'title' not found on object of type 'id'
error: 1 errors parsing expression
(lldb) po ((Thing*)[things objectAtIndex:0]).title
(NSString *) $14 = 0x00005944 Basic
(lldb) po [[things objectAtIndex:0] valueForKey:@"title"]
(id) $15 = 0x00005944 Basic

Whew!