36.不要使用retainCount

《编写高质量iOS与OS X代码的52个有效方法》--第五章 第36条
(ps:此乃读书笔记,加深记忆,仅供大家参考)


第36条 不要使用retainCount

NSObject协议中定义了下列方法,用于查询对象当前的保留计数:

- (NSUInteger)retainCount

然而ARC已经将此方法废弃了。若在不启用ARC的环境下编程,那么扔可调用此方法,所以还是必须讲清楚为何不应使用此方法。

这个方法看上去似乎挺合理的、挺有用的。但问题在于,保留计数的绝对值一般都与开发者所应留意的事情完全无关。即便是在调试时才调用此方法,通常也还是无所助益的。

此方法之所以无用,其首要原因在于:它所返回的保留计数只是某个给定时间点上的值。该方法并未考虑到系统会稍后把自动释放池清空,因而不会将后续的释放操作从返回值里减去,这样的话,此值就未必能真实反映实际的保留计数了。

有下面这段代码:

NSString *stirng = @"Some string";
NSLog(@"string retainCount = %lu", [stirng retainCount]);

NSNumber *numberI = @1;
NSLog(@"numberI retainCount = %lu", [numberI retainCount]);

NSNumber *numberF = @3.14f;
NSLog(@"numberF retainCount = %lu", [numberF retainCount]);

在64位Mac OS X 10.8.2系统中,用Clang4.1编译后,这段代码输出的消息如下:

string retainCount = 18446744073709551615
numberI retainCount = 9223372036854775807
numberF retainCount = 1

第一个对象的保留计数是2^64 - 1,第二个对象的保留计数是2^63 - 1.由于二者皆为“单例对象”(singleton object),所以其保留计数都很大。系统会尽可能把NSStirng实现成单例对象。如果字符串像本例所举的这样,是个编译常量(compile-time constant),那么就可以这样来实现了。在这用情况下,编译器会把NSString对象所表示的数据放到应用程序的二进制文件里,这样的话,运行程序时就可以直接用了,无须再创建NSString对象。NSNumber也类似,它使用了一种叫做“标签指针”(tagged pointer)的概念来标注特定类型的数值。这种做法不使用NSNumber对象,而是把与数值有关的全部消息都放在指针值里面。运行期系统会在消息派发(参见第11条)期间检测到这种标签指针,并对它执行相应操作,使其行为看上去和真正的NSNumber对象一样。这种优化只在某些场合使用,比如范例中的浮点数对象就没有优化,所以其保留计数就是1。

另外,像刚才所说的那种单例对象,其保留计数绝对不会变。这种对象的保留及释放操作都是“空操作”(no-op)。

那么,只为了调试而使用retainCount方法行不行呢?即便只为调试,此方法也不是很有用。以下列代码为例:

id object = [self createObject];
[opaqueObject doSomethingWithObject:object];
NSLog(@"retainCount = %lu", [object retainCount]);

object的保留计数是多少呢?这个计数可以是任意值。“doSomethingWithObject:”方法也许会将对象加到多个collectin中,而这些collection均会保留此对象。这个方法还可能会多次保留并自动释放此对象,而其中某些自动释放操作要留待系统稍后清空自动释放池时才执行。因此,保留计数的实际值就不是那么有用了。

要点

  • 对象的保留计数看似有用,实则不然,因为任何给定时间点上的“绝对保留计数”(absolute retain count)都无法反映对象生命期的全貌。
  • 引入ARC之后,retainCount方法就正式废止了,在ARC下调用该方法会导致编译器报错。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 29.理解引用计数 Objective-C语言使用引用计数来管理内存,也就是说,每个对象都有个可以递增或递减的计数...
    Code_Ninja阅读 5,485评论 1 3
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,395评论 30 472
  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 6,067评论 1 16
  • 第 23 条:通过委托与数据源协议进行对象间通信 Objective-C 可以使用 “委托模式”(Delegate...
    德山_阅读 4,330评论 0 2
  • 内存管理是程序在运行时分配内存、使用内存,并在程序完成时释放内存的过程。在Objective-C中,也被看作是在众...
    蹲瓜阅读 8,462评论 1 8

友情链接更多精彩内容