MRC 全称 Manual Reference Counting,也称为 MRR(manual retain-release),手动引用计数内存管理,即开发者需要手动控制对象的引用计数来管理对象的内存。
在 MRC 年代,我们经常需要写 retain
、release
、autorelease
等方法来手动管理对象内存,然而这些方法在 ARC 是禁止调用的,调用会引起编译报错。
在 MRC 中增加的引用计数都是需要自己手动管理的,所以我们需要知道哪些方式会引起引用计数变化:
对象操作 | OC中对应的方法 | 引用计数的变化 |
---|---|---|
生成并持有对象 | alloc/new/copy/mutableCopy等 | +1 |
持有对象 | retain | +1 |
释放对象 | release | -1 |
废弃对象 | dealloc | - |
1.四个法则
- 自己生成的对象,自己持有。
/*
* 自己生成并持有该对象
*/
id obj0 = [[NSObeject alloc] init];
id obj1 = [NSObeject new];
- 非自己生成的对象,自己也能持有。
/*
* 持有非自己生成的对象
*/
id obj = [NSArray array]; // 非自己生成的对象,且该对象存在,但自己不持有
[obj retain]; // 自己持有对象
- 不在需要自己持有对象的时候,释放。
/*
* 不在需要自己持有的对象的时候,释放
*/
id obj = [[NSObeject alloc] init]; // 此时持有对象
[obj release]; // 释放对象
/*
* 指向对象的指针仍就被保留在obj这个变量中
* 但对象已经释放,不可访问
*/
- 非自己持有的对象无需释放。
/*
* 非自己持有的对象无法释放
*/
id obj = [NSArray array]; // 非自己生成的对象,且该对象存在,但自己不持有
[obj release]; // ~~~此时将运行时crash 或编译器报error~~~ 非 ARC 下,调用该方法会导致编译器报 issues。此操作的行为是未定义的,可能会导致运行时 crash 或者其它未知行为
2.非自己生成的对象,且该对象存在,但自己不持有
其中关于非自己生成的对象,且该对象存在,但自己不持有是如何实现的呢?这个特性是使用 autorelease
来实现的,示例代码如下:
- (id) getAObjNotRetain {
id obj = [[NSObject alloc] init]; // 自己持有对象
[obj autorelease]; // 取得的对象存在,但自己不持有该对象
return obj;
}
使用 autorelease
方法可以使取得的对象存在,但自己不持有对象。autorelease
使得对象在超出生命周期后能正确的被释放(通过调用 release
方法)。在调用 release
后,对象会被立即释放,而调用 autorelease
后,对象不会被立即释放,而是注册到 autoreleasepool
中,经过一段时间后 pool
结束,此时调用 release
方法,对象被释放。
像 [NSMutableArray array]
、[NSArray array]
都可以取得谁都不持有的对象,这些方法都是通过 autorelease
实现的。
3.dealloc
NSObject 协议中定义的内存管理方法与遵守这些方法命名约定的自定义方法的组合提供了用于引用计数环境中的内存管理的基本模型。NSObject 类还定义了一个dealloc
方法,该方法在对象被销毁时自动调用。
网友评论