Or: How to Make NSLog()
Useful With Your Objects
Say you have an archaically named NSArray
that you want to inspect — it’s easy to do, since NSLog(@"The bestiary is %@", bestiary);
prints out the array’s contents
2008-09-16 19:46:06.445 Tester[2678:10b] The bestiary is (
Cheetah,
Pumpa,
Jaguar,
Panther,
Tiger,
Leopard
)
But if you try to NSLog
your own object, you get pretty useless output, like
myObject = <MyObject: 0x53f330>
Fortunately, it’s easy to fix! Just implement the method -(NSString*) description;
and whatever it returns will be printed by NSLog
and GDB (po object
, will print object in GDB and the Xcode debugging console).
Here’s an (unfortunately complex) example,
- (NSString*) description;
{
return [NSString stringWithFormat:@"<%@ %p> = {\n\tquestion=%@,\n\tanswer=%@,\n\tsource=%@\n}", [self className], self, self.question, self.answer, self.source];
}
output:
myObject = <MyObject 0x53eed0> = {
question=What is the Best Thing Ever Of All Times, Ever?,
answer=The Internet!,
source=http://www.cabel.name/2008/01/2007-cabel-yay-awards.html
}
Useful Formatters and such
These macros have made my debugging-life easer.
%p
tells NSLog
to print the address of a pointer.
-className
returns gives the name of a class as an NSString
.
Don’t manually print out a Cocoa struct
, ever, there are already NSStringTo*
functions to do that for you, like NSStringFromPoint()
.
NSStringFromSelector()
works as advertized (and paired with NSSelectorFromString()
is very useful in general).
%lld
tells NSLog
to print a long long
(64-bit integer). See also, printf
reference.
%Lf
tells NSLog
to print a long double
. See also, printf
reference.
Best Practices
Whenever you make a new object, I strongly recommended immediately implementing a description
method, and religiously keeping it up to date (it’s not hard, honest!). This won’t fix bugs, but it will make finding some of them much easier.