好玩的debugDescription & runtime(debug模式下调试model)

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, 如下图:

这里写图片描述

</p>
</p>

debugDescription

现在问题继续来了..
在项目中NSLog语句往往也很多. 如果重写description方法. 在控制台则会打印出很多属性. 看着就不舒服~~而且还有一个问题就是, 有时候我们其实并不需要打印model的属性.. 那这样重写description方法反而适得其反了! 所有, 现在有一个解决方案就是重写debugDescription方法


什么是debugDescription? 其实debugDescriptiondescription是一样的效果. 只不过唯一的区别就是debugDescription是在Xcode控制台里使用po命令的时候调用的~!


debugDescription的实现其实也就是调用了description方法而已

so, 在开发过程中并且model调试的时候, 笔者推荐重写debugDescription方法而不是重写description方法. 当需要打印model的属性的时候, 在控制台里使用po命令即可. 如下在此修改后的.m文件

#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

看如下图, 分别使用了NSLogpo命令的打印


这里写图片描述

结果:

这里写图片描述

这就达到了我们想要的效果, 如果需要打印model的属性, 打个断点然后使用po命令即可

demo地址

最后,附上本文章的一个小demo示例代码,已放在github上。
https://github.com/DemoMania/DebugDescriptionDemo

总结

  • model调试的时候, 推荐重写debugDescription而不是description
  • 利用runtime技术动态获取class的属性
  • base基类里重写debugDescription方法,随后所有model继承与baseModel即可。
  • 在重写的debugDescription的方法里最好不要调用自身debugDescription([self debugDescription])
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,357评论 25 708
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,232评论 0 7
  • 最近在面试,面试过程中问到了一些Xcode常用的调试技巧问题。平常开发过程中用的还挺顺手的,但你要突然让我说,确实...
    远0阅读 643评论 2 8
  • 闫秋爱上了她隔壁班的男生,在这高一上学期的期中考试后,在这个炎热的夏季,他叫杜震,闫秋爱上他的原因很简单,因为他会...
    清梦飞扬阅读 1,095评论 0 3
  • 这里是温柔的,坚硬和粗糙的围墙里,我就躲在那,安心的看着眼前的星星。 第一,不被情绪冲昏了头脑,像一个无头...
    眼白阅读 309评论 0 0