Objective-C通过引用计数来管理内存,每个对象都有一个计数器,其值表明还有多少个对象同此对象之间存在引用关系。每个对象在创建之际其retainCount设置为1,retain/copy会使引用计数递增,而release则会使其引用计数递减。
在NSObject协议中定义了retainCount的方法,用于查询对象当前的引用计数,方法的定义如下:
-(NSUInteger)retainCount
虽然说在ARC的情况下该方法已经被废弃,这和在ARC中使用retain、release、autorelease方法一样编译器会报错,若在不启用ARC的开发环境下仍然可以调用此方法而编译器不会报错。虽然此方法已经被正式废弃了但是还是经常有人会误解它,其实这个方法根本就不应该被调用。这个方法看上去似乎挺有用的,毕竟返回了保留的引用计数,似乎可以通过retainCount的值来决定对象能否被释放等。但问题在于,保留计数的绝对值一般都与开发者所留意的事情完全无关。
此方法之所以没有用处其首要原因在于:
它所返回的保留计数只是在某个给定时间点上的值,并未考虑到系统会稍后吧自动释放池清空,因而不会将后续的释放操作从返回值中减去,这样的话就未必能真实地反映实际的保留计数了。
实例分析
对于下面的这种想要释放对于的写法非常糟糕:
while([obj retainCount]) {
[obj release];
}
错误分析:
1、这种写法的第一个错误是,没有考虑到后续的自动释放操作,只是不停的通过释放操作来减少保留计数,直到对象资源被系统回收,假如此对象也在自动释放池里,那么稍后系统清空自动释放池时还要将它再释放一次,这将导致程序异常;
2、第二个错误在于,retainCount可能永远不返回0,因为有时系统会优化对象的释放行为在保留计数还是1的时候就把对象给回收了,只有系统不打算这么优化时,计数值才会递减至0,因此保留计数可能永远不为0。
要点小结
1、对象的保留计数看似有用,实则不然,因为任何给定时间点上的“绝对保留计数”(absolute retain count)都无法反映对象生命周期的全貌;
2、引入ARC后,retainCount正式被废弃使用,在ARC环境下调用该方法会导致编译器报错;
3、不应该总是依赖保留计数的具体值来编码,即便只是为了调试。