【iOS】引用计数
引用计数
- 自动引用计数
- 引用计数
- 内存管理的思考方式
- 自己生成的对象,自己所持有
- 非自己生成的对象,自己也能持有
- 不再需要自己持有的对象时释放
- 无法释放非自己持有的对象
自动引用计数
自动引用计数(ARC,Automatic Reference Counting)是指内存管理中对引用采用自动计数的技术。对于ARC技术来说,最重要的就是***在LLVM编译器中设置ARC为有效状态,就不用再次输入retain和release代码***。
当满足下列条件时,就无须手动输入retain和release代码了:
- 使用XCode4.2或以上版本
- 使用LLVM编译器3.0或以上版本
- 编译器选项中设置ARC为有效
引用计数
我们可以用一个房间内开关灯来说明引用计数这个问题,当房间内进入第一个人时开灯,最后一个人离开时关灯,在这个过程中,需要照明的人数就是引用数。
如上图所示,就是引用计数的原理
那么对于OC对象来说,下图即可展示两者的对应动作:
如此来说,OC中的内存管理即入下图所示:
内存管理的思考方式
在内存管理中,正确、客观的思考方式是:
- 自己生成的对象,自己所持有
- 非自己生成的对象,自己所持有
- 不再需要自己持有的对象时释放
- 非自己持有的对象无法释放
在上面的思考方式中多次出现“生成”、“持有”、“释放”三个词,在OC内存管理中还有“废弃”一词,下面展示各个词表示的OC方法:
操作对象 | Objective-C方法 |
---|---|
生成并持有对象 | alloc/new/copy/mutableCopy等方法 |
持有对象 | retain方法 |
释放对象 | release方法 |
废弃对象 | dealloc方法 |
这些有关 Objective-C 内存管理的方法,实际上不包括在该语言中,而是包含在 Cocoa 框架中用于 OS X、iOS 应用开发。Cocoa 框架中 Foundation 框架类库的 NSObject 类担负内存管理的职责。Objective-C内存管理中的 allocretain/release/dealloc 方法分别指代 NSObject 类的 alloc 类方法、retain 实例方法、release 实例方法和 dealloc 实例方法。
自己生成的对象,自己所持有
使用以下名称开头的方法名意味着自己生成的对象只有自己持有:
- alloc
- new
- copy
- mutableCopy
代码格式:
id obj = [[NSObject alloc] init];
id obj = [NSObject new];
//注意:上面两种生成并持有对象的方法是完全一致的
对于以下这些名称开头的方法名也意味着自己生成并持有对象:
allocMyObject
newThatObject
copyThis
mutableCopyYourObject
非自己生成的对象,自己也能持有
除了上述方法以外的方法生成的对象,因为不是自己生成并持有,所以自己不是该对象的持有者。下面举例说明
id obj = [NSMutableArray array];
[obj retain];
//通过retain方法,非自己生成的对象跟用alloc等方法生成的对象一样,成了自己所持有的。
不再需要自己持有的对象时释放
自己持有的对象,一旦不再需要时,持有者有义务释放该对象,使用release
方法释放。
id obj = [[NSObject alloc] init];
[obj release];
这里举了一个例子说明,当使用retain
方法变成自己持有的时候,也可以使用release
释放。
无法释放非自己持有的对象
我们在使用alloc等方法或者retain方法将持有者变成自己时,需要在不需要时释放该对象,但是如果是非自己持有的对象,我们不能释放他,如果释放就会造成应用程序崩溃。例如自己生成对象后不需要时释放了两次,就会导致这个问题。
id obj = [[NSObject alloc] init];
[obj release];
[obj release];
这样做,由于第一次已经释放过了,再次释放就会导致应用程序崩溃。
autorelease和release的区别
当我们使用alloc等方法向实现取得的对象存在但是自己不持有就需要用到
autorelease
方法。下面举例说明:
id obj = [[NSObject alloc] init];
[obj autorelease];
使用
autorelease
方法就可以实现,令对象在超出指定的生存范围时能够自动并正确的释放掉,在我们上文中举例的array就是通过调用autorelease
实现的,当然,也可以通过retain
方法再将其变成自己持有的。
上图即展示了autorelease和release的区别。