本条要点:(作者总结)

  • 实现 description 方法返回一个有意义的字符串,用以描述该实例。
  • 若想在调试时打印出来更详尽的对象描述信息,则应实现 debugDescription 方法。

  调试程序时,经常需要打印并查看对象信息。一种办法是编写代码把对象的全部属性都输出到日志中。不过最常用的做法还是像下面这样:

1 NSLog(@"object = %@", object);

  在构建需要打印到日志的字符串时,object 对象会收到 description 消息,该方法所返回的描述信息将取代 “格式字符串” (format string)里的 “%@”。比方说,object 是个数组,若用下列代码打印其信息:

1         NSArray *object = @[@"A string", @(123)];
2         NSLog(@"object = %@", object);

  则会输出:

1 object = (
2     "A string",
3     123
4 )

  然而,如果在自定义的类上这么做,那么输出的信息却是下面这样:

1 object = <EOCPerson: 0x7fd9a1600600>

  与 object 为数组时输出的信息相比,上面这种内容不太有用。除非在自己的类里覆写 description 方法,否则打印信息时就会调用 NSObject 类所实现的默认方法。此方法定义在 NSObject 协议里,不过 NSObject 类也实现了它。因为 NSObject 并不是唯一的 “根类”,所以许多方法都要定义在 NSObject 协议里,比方说,NSProxy 也是一个遵从了 NSObject 协议的 “根类”。由于 description 等方法定义在 NSObject 协议里,因此像 NSProxy 这种 “根类”及其子类也必须实现它们。如前所见,这些实现好的方法并没有打印出较为有用的内容,只不过是输出了类名和对象的内存地址。只有在你想判断两指针是否真的指向同一对象时,这种信息才有用处。除此之外,再也看不出其他有用的内容了。我们想打印出来的对象信息应该比这更多才对。

  要想输出更为有用的信息也很简单,只需覆写 description 方法并将描述此对象的字符串返回即可。例如,有下面这个代表个人信息的类:

 1 #import <Foundation/Foundation.h>
 2
 3 @interface EOCPerson : NSObject
 4
 5 @property (nonatomic, copy, readonly) NSString *firstName;
 6 @property (nonatomic, copy, readonly) NSString *lastName;
 7
 8 - (instancetype)initWithFirstName:(NSString *)firstName
 9                          lastName:(NSString *)lastName;
10
11 @end

 1 #import "EOCPerson.h"
 2
 3 @implementation EOCPerson
 4
 5 - (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
 6     if (self = [super init]) {
 7         _firstName = [firstName copy];
 8         _lastName = [lastName copy];
 9     }
10     return self;
11 }
12
13 @end

  该类的 description 方法通常可以这样实现:

1 - (NSString *)description {
2     return [NSString stringWithFormat:@"<%@: %p, \"%@ %@\">", [self class], self, _firstName, _lastName];
3 }

  假如按上面的代码来写,那么 EOCPerson 对象就会输出如下格式的信息:

1     EOCPerson *person = [[EOCPerson alloc] initWithFirstName:@"Bob" lastName:@"sSmith"];
2     NSLog(@"person = %@", person);

  打印信息:

1 person = <EOCPerson: 0x60000002b400, "Bob sSmith">

  这样就必覆写之前所输出的信息更加清楚,也更有用了。笔者建议: 在新实现的 description 方法中,也应该像默认的实现那样,打印出类的名字和指针地址,因为这些内容有时也许会用到。不过大家刚才也看到了,NSArray 类的对象就没有打印这两项内容。显然,在实现 description 方法时,没有固定规则可循,应根据当前对象来决定在 description 方法里打印何种信息。

  有个简单的办法,可以在 description 中输出很多互不相同的信息,那就是借助 NSDictionary 类的 description 方法。此方法输出的信息的格式如下:

1 {
2     key: value;
3     foo: bar;
4 }

  在自定义的 description 方法中,把待打印的信息存放到字典里面,然后将字典对象的 description 方法所输出的内容包含在字符串里并返回,这样就可以实现精简的信息输出方式了。例如,下面这个类表示某地点的名称和地理坐标(纬度和经度):

 1 #import <Foundation/Foundation.h>
 2
 3 @interface EOCLocation : NSObject
 4
 5 @property (nonatomic, copy, readonly) NSString *title;
 6 @property (nonatomic, assign, readonly) float latitude;
 7 @property (nonatomic, assign, readonly) float longitude;
 8
 9 - (instancetype)initWithTitle:(NSString *)title latitude:(float)latitude longitude:(float)longitude;
10
11 @end
12
13 #import "EOCLocation.h"
14
15 @implementation EOCLocation
16
17 - (instancetype)initWithTitle:(NSString *)title latitude:(float)latitude longitude:(float)longitude {
18     if (self = [super init]) {
19         _title = [title copy];
20         _latitude = latitude;
21         _longitude = longitude;
22     }
23     return self;
24 }
25
26 @end

  要是这个类的 description 方法能够打印出地名和经纬度就好了。我们可以像下面这样编写 description 方法,用 NSDictionary 来实现此功能:

1 - (NSString *)description {
2     return [NSString stringWithFormat:@"<%@: %p, %@>", [self class], self, @{@"title": _title, @"latitude": @(_latitude), @"longitude": @(_longitude)}];
3 }

  输出的信息格式是:

1 <EOCLocation: 0x60000002caa0, {
2     latitude = 34;
3     longitude = "163.45";
4     title = Beijing;
5 }>

  这比仅仅输出指针和类名要有用多了,而且对象中的每条属性都能打印的很好。也可以在格式字符串中直接为每个实例变量留好位置,然后逐个打印出来,不过,用 NSDictionary 来实现此功能可以令代码更易维护: 如果以后还要向类中新增属性,并且要在 description 方法中打印,那么只需修改字典内容即可。

  NSObject 协议中还又个方法要注意,那就是 debugDescription,此方法的用意与 description 非常相似。二者区别在于,debugDescription 方法是开发者在调试器(debugger)中以控制台命令打印对象时才调用的。在 NSObject 类的默认实现中,此方法只是直接调用了 description。以 EOCPerson 类为例,我们在创建实例所用的代码后面插入断点,然后通过调试器(假设使用 LLDB)运行程序,使之暂停于此:

1     EOCPerson *person = [[EOCPerson alloc] initWithFirstName:@"Bob" lastName:@"sSmith"];
2     NSLog(@"person = %@", person);3  Breakpoint here

  当程序运行到断点时,开发者就可以向调试控制台里输入命令了。LLDB 的 “po” 命令可以完成对象打印(print-object)工作,其输出如下:

1 po person
2 <EOCPerson: 0x60000002cee0, "Bob sSmith">

  请注意,控制台中的内容是 debugDescription 所返回的信息。

  你也许只想把人名放在 EOCPerson 对象的普通描述信息中,而把更详尽的内容放在调试所用的描述信息里,此时可用下列代码实现这两个方法:

1 - (NSString *)description {
2     return [NSString stringWithFormat:@"<%@: %p, \"%@ %@\">", [self class], self, _firstName, _lastName];
3 }
4
5 - (NSString *)debugDescription {
6     return [NSString stringWithFormat:@"<%@: %p, \"%@ %@\">", [self class], self, _firstName, _lastName];
7 }

  写好之后,再把钢才的程序码运行一遍,这次 po 命令所打印出来的对象信息如下所示:

  你可能不想把类名与指针地址这种额外内容放在普通的描述信息里,但是却希望调试的时候能够很方便地看到它们,在此情况下,就可以使用这种输出方式来实现。Foundation 框架的 NSArray 类就是这么做的。例如:

1     NSArray *array = @[@"Effective Objective-C 2.0", @(123), @(YES)];
2     NSLog(@"array = %@", array);
3 // Breakpoint here

  运行上述程序码,待其停在断点处,然后用 po 命令打印数组对象,就可以看到如下信息:

 1 array = (
 2     "Effective Objective-C 2.0",
 3     123,
 4     1
 5 )
 6 (lldb) po array
 7 <__NSArrayI 0x60000004f270>(
 8 Effective Objective-C 2.0,
 9 123,
10 1
11 )

END

转载于:https://www.cnblogs.com/chmhml/p/7129176.html

第17条:实现description方法相关推荐

  1. 17条避坑指南:一份来自谷歌的数据库经验贴

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://medium.com/@rak ...

  2. [Objective-c 基础 - 2.10] description方法

    A. 实例对象打印-description 1.当使用NSLog函数并且使用%@占位符的时候,会调用对象的-description方法 2.拿到-description的返回值,显示到console中 ...

  3. IOS中的swift和oc关于对象模型的description方法重写

    IOS中的swift和oc关于对象模型的description方法重写 先讲OC的,oc比较重要,放在最前面. 首先创建一个cocoa Touch Class,继承NSObject, 命名Person ...

  4. 语言基础之description方法

    1.description方法的一般用处 1: // 指针变量的地址 2: NSLog(@"%p", &p); 3: // 对象的地址 4: NSLog(@"%p ...

  5. SQL 分页查询语句大全即(查找第N到M条记录的方法)

    SQL 分页查询语句大全即(查找第N到M条记录的方法) 第一种方法,我的原创方法 row=2 表示分页行数 page=1 表示页码 getnum=row*page select * from  (se ...

  6. word没有显示endnote_Word2007或2010未显示EndNote工具条的解决方法 | 科研动力

    Word 2007或2010未显示EndNote工具条的解決方法:1.修复安装:2.修改加载项:3.管理加载中心. 有时在Word 2007/ 2010可能会不显示EndNote工具条,造成这种情况最 ...

  7. 1对多 只取一条 mysql_MySQL 多表关联一对多查询实现取最新一条数据的方法示例...

    本文实例讲述了MySQL 多表关联一对多查询实现取最新一条数据的方法.分享给大家供大家参考,具体如下: MySQL 多表关联一对多查询取最新的一条数据 遇到的问题 多表关联一对多查询取最新的一条数据, ...

  8. 求生之路:学术生涯的17条简单生存法则

    求生之路:博士生涯的17条简单生存法则 总结与节选 英文原文链接:http://www.maiconference.com/uploads/1/1/0/7/110798645/survive-your ...

  9. Unix哲学17条原则的新感悟

    现在,说到操作系统,谈论最多的就是Android,ios,Linux,mac os,windows,已经很少有人会使用到unix系统了,除了一些企业内部的系统,和编程爱好者社区会交流外,基本上已经绝迹 ...

最新文章

  1. Springboot+vue前后端分离考试系统
  2. STM32 基础系列教程 8 - 互补PWM
  3. 野路子码农系列(3)plotly可视化的简单套路
  4. 华为鸿蒙os系统有哪些黑科技,华为首款搭载鸿蒙os智慧产品除了鸿蒙系统还有这黑科技...
  5. docker多个容器一起打包_docker如何将容器打包成镜像
  6. sap实施和开发哪个前景_2021年了!还不知道 SAP顾问的职业前景?
  7. springBoot中自定义的yml文件引用的方式
  8. 利用Vivado封装DCP文件基本流程
  9. python猴子偷桃递归_C++猴子偷桃问题
  10. 【燕郊】【2015-12-31】【知乎】
  11. Android如何解析Intent
  12. python对一串列表计数然后画扇形图_python – 按行分组的DataFrame列的高效计数
  13. 例3.4 二叉树遍历 - 九度教程第32题(二叉树)
  14. illustrator插件-常用功能开发-置入多页面PDF-js脚本开发-AI插件
  15. jdk动态代理的实现流程(事务处理)
  16. C语言自学之路十三(详解C语言初阶指针)
  17. snakeyaml操作yml文件中注释的处理
  18. nds android7.0模拟器,NDS用MD模拟器jEnesisDS 0.7
  19. Jetson TX2 arm板子刷机,安装Caffe
  20. s7-200 smart中VD,VW这类变量在INTOUCH中如何对应

热门文章

  1. QFile和QDir
  2. 生产型企业如何选择靠谱的供应商?
  3. java中的值传递和引用传递的区别?
  4. 〖Python零基础入门篇㊸〗- 异常处理的避坑指南
  5. 中文版Dreamweaver+Flash+Photoshop网页制作从入门到精通(CS4版) PDF扫描版
  6. js实现九九乘法表(两种方法)
  7. YC指的是Y Combinator和陆奇
  8. Linux top命令的用法详细详解
  9. 数据结构——时间复杂度和算法复杂度
  10. 计算机硬件知识总结,计算机硬件知识总结(三)