调试程序时,经常需要打印并查看对象信息。一种办法是编写代码吧对象的全部属性都输出道日志中。不过最常用的方法还是像下面这样:
NSLog(@"object = %@", object);
如果是自定义对象就不会打印出较为有用的内容,只不过输出了类名和对象的内存地址:
object = <EOCPerson: 0x7fd9a1600600>
要想输出更为有用的信息也很简单,只要覆写description方法并将描述此对象的字符串返回即可。例如,下面有个代表个人信息的类:
#import <Foundation/Foundation.h>
@interface EOCPerson : NSObject
@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;
- (id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;
@end
@implementation EOCPerson
- (id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName
{
if ((self = [super init])) {
_firstName = [firstName copy];
_lastName = [lastName copy];
}
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@:%p, \"%@ %@\">",[self class], self, _firstName, _lastName];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
EOCPerson *person = [[EOCPerson alloc] initWithFirstName:@"郭" lastName:@"爽"];
NSLog(@"person = %@", person);
}
return 0;
}
输出:
person = <EOCPerson:0x100106870, "郭 爽">
Program ended with exit code: 0
NSObject协议中还有个方法要注意,那就是debugDescription,此方法的用意与description非常相似。二者的区别在于,debugDescription方法是开发者在调试器中已控制台命令打印对象时才调用的。在NSObject类的默认实现中,此方法只是直接调用了description。以EOCPerson类为例,我们在创建实例所用的代码后面插入断点,然后通过调试器(假设使用LLDB)运行程序,使之暂停于此:
EOCPerson *person = [[EOCPerson alloc] initWithFirstName:@"郭" lastName:@"爽"];
NSLog(@"person = %@", person);
//breakpoint here
当程序运行至断点处,开发者使用LLDB的“po”命令可以完成对象的打印工作输出如下:
(lldb) po person
<EOCPerson:0x100601d60, "郭 爽">
改变“po”命令的输出信息可以覆写debugDescription方法:
- (NSString *)debugDescription
{
return [NSString stringWithFormat:@"<debugDescription----->%@:%p, \"%@ %@\">",[self class], self, _firstName, _lastName];
}
再同样断电处使用“po”命令输出如下:
(lldb) po person
<debugDescription----->EOCPerson:0x100603720, "郭 爽">