好玩的debugDescription(debug模式下调试model)
来自: http://www.jianshu.com/p/4e1f6938c1ca

description
在开发过程中, 往往会有很多的model来装载属性. 而在开发期间经常会进行调试查看model里的属性值是否正确. 那么问题来了, 在 objective-c 里使用 NSLog("%@",model) 这行代码打印出来的却是 model 的地址. 不是我们所想要的结果~! 看图:
那么问题又来了?有没有办法解决这个问题尼,答案那就是有~!只需要重写 - (NSString *)description 方法即可。如下代码:
.h文件
#import <Foundation/Foundation.h> @interface TestModel : NSObject @property (copy,nonatomic) NSString *text; @property (assign,nonatomic) NSInteger index; @end
.m文件
#import "TestModel.h" @implementation TestModel - (NSString *)description { return [NSString stringWithFormat:@"text:%@--index:%zi",self.text,self.index]; } @end
然后这时候在使用 NSLog("%@",model) 这行代码就能打印我们想要的结果了。 看如下图:

那么问题继续来了...
如果model里有 N 多个属性尼, 可能 10 个, 可能 20 个... 难道要在 description 方法里一个一个写属性并拼接返回? 你不嫌麻烦, 我光看着都蛋疼了... 所以我们可以采用 runtime 技术来动态获取属性并返回. 如下修改后的.m文件代码:
修改后的.m文件
#import "TestModel.h" #import <objc/runtime.h>//导入runtime头文件 @implementation TestModel - (NSString *)description { //初始化一个字典 NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; //得到当前class的所有属性 uint count; objc_property_t *properties = class_copyPropertyList([self class], &count); //循环并用KVC得到每个属性的值 for (int i = 0; i<count; i++) { objc_property_t property = properties[i]; NSString *name = @(property_getName(property)); id value = [self valueForKey:name]?:@"nil";//默认值为nil字符串 [dictionary setObject:value forKey:name];//装载到字典里 } //释放 free(properties); //return return [NSString stringWithFormat:@"<%@: %p> -- %@",[self class],self,dictionary]; } @end
然后在打印 model , 如下图:

debugDescription
现在问题继续来了..
在项目中 NSLog 语句往往也很多. 如果重写 description 方法. 在控制台则会打印出很多属性. 看着就不舒服~~而且还有一个问题就是, 有时候我们其实并不需要打印 model 的属性.. 那这样重写 description 方法反而 适得其反 了! 所有, 现在有一个解决方案就是重写 debugDescription 方法
什么是 debugDescription ? 其实 debugDescription 和 description 是一样的效果. 只不过唯一的区别就是 debugDescription 是在 Xcode 控制台里使用 po 命令的时候调用的~!
而 debugDescription 的实现其实也就是调用了 description 方法而已
so, 在开发过程中并且 model 调试的时候, 笔者推荐重写 debugDescription 方法而不是重写 description 方法. 当需要打印 model 的属性的时候, 在控制台里使用 po 命令即可. 如下在此修改后的 .m文件
</div>#import "TestModel.h" #import <objc/runtime.h>//导入runtime头文件 @implementation TestModel // 重写debugDescription, 而不是description - (NSString *)debugDescription { //声明一个字典 NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; //得到当前class的所有属性 uint count; objc_property_t *properties = class_copyPropertyList([self class], &count); //循环并用KVC得到每个属性的值 for (int i = 0; i<count; i++) { objc_property_t property = properties[i]; NSString *name = @(property_getName(property)); id value = [self valueForKey:name]?:@"nil";//默认值为nil字符串 [dictionary setObject:value forKey:name];//装载到字典里 } //释放 free(properties); //return return [NSString stringWithFormat:@"<%@: %p> -- %@",[self class],self,dictionary]; } @end
看如下图, 分别使用了 NSLog 和 po 命令的打印

结果:

这就达到了我们想要的效果, 如果需要打印 model 的属性, 打个断点然后使用 po 命令即可
</div>demo地址
最后,附上本文章的一个小demo示例代码,已放在github上。
https://github.com/DemoMania/DebugDescriptionDemo总结
- model 调试的时候, 推荐重写 debugDescription 而不是 description
- 利用 runtime 技术动态获取 class 的属性
- 在 base 基类里重写 debugDescription 方法,随后所有model继承与 baseModel 即可。
- 在重写的 debugDescription 的方法里最好不要调用自身 debugDescription([self debugDescription])