曾静的博客

但行好事,莫问前程.

嗨,我是曾静 (@devzeng),目前暂居深圳。


这是我用来记录平日学习笔记的地方,欢迎您的访问.

不要使用retainCount

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、不应该总是依赖保留计数的具体值来编码,即便只是为了调试。

最近的文章

iOS中的单例设计模式

在一个iOS应用的生命周期中,有时候我们只需要某个类的一个实例。例如,iOS设备都有一个重力加速计硬件设备,要访问设备在X轴、Y轴和Z轴上的重力加速度,就必然有一个类能够与硬件设备沟通来实时获取这些数据,这个类就是UIAccelerometer。除了实时地获取数据该类还能保持X轴、Y轴和Z轴的状态,但这个类只要一个实例就够了,如果有多个实例就会占用过多的内存。单例模式简单实现在objective-c中要实现一个单例类,至少需要做以下四个步骤:(推荐使用宏的方式来创建)(1)为单例对象实现一...…

iOS继续阅读
更早的文章

iOS企业级应用部署

在iOS开发计划中有一种是iOS Developer Enterprise Program(iOS开发者企业级计划),对于这种开发者证书发布的应用程序是无法上传到Apple App Store上的,目前对于这种企业级开发的应用程序最好的分发方式是部署到内网服务器上通过网络进行下载。IN-HOUSE应用程序分发下面介绍下使用网络方式进行部署的方式,用户直接在iPhone/iPad的Safari浏览器里面输入URL地址即可安装,如在浏览器输入http://www.itools.cn能出现如下的...…

iOS继续阅读