0%

Objective-C内存管理之引用计数

Objective-C中的内存管理,也就是引用计数, 可以用如下方式进行思考:

  • 自己生成的对象, 自己持有.
  • 非自己生成的对象, 自己也能持有.
  • 不再需要自己持有的对象时释放对象
  • 非自己持有的对象无法释放

“生成”, “持有”, “释放”, “废弃”四个词对应的Objective-C方法如下:

  • 生成: alloc/new/copy/mutableCopy 等方法
  • 持有: retain方法
  • 释放: release方法
  • 废弃: dealloc方法

这些内存管理相关的方法, 实际上不包括在语言本身中, 而是包含在Cocoa框架中. Cocoa框架中Foundation框架类库的NSObject类负责进行内存管理.

自己生成并持有对象

使用以下名称开头的方法意味着自己生成的对象只有自己持有:

  • alloc
  • new
  • copy
  • mutableCopy

alloc/new示例:

id obj = [[NSObject alloc]init];
id obj = [NSObject new];

copy方法生成不可变的对象, 而mutableCopy生成可变的对象.

非自己生成的对象, 自己也能持有

用alloc/new/copy/mutableCopy之外的方法取得的对象, 自己也能持有:

//取得非自己生成的对象
id obj = [NSMutableArray array];	

//此时使用release会crash
//[obj release];

//持有对象
[obj retain];

通过retain方法, 能持有非自己生成的对象.

不再需要自己持有的对象时释放对象

自己生成持有的对象, 一旦不再需要, 持有者有义务释放该对象. 释放使用release方法.

id obj = [[NSObject alloc]init];
[obj release];

非自己生成,但自己持有的对象, 若使用retain方法持有之后, 不需要时, 也要使用release方法释放.

NSMutableArray *array = [NSMutableArray array];
[array retain];
[array release];

那么调用[NSMutableArray array]方法取得对象存在, 但自己不持有对象, 是怎么实现的呢?

- (id)object {
    //持有对象
    id obj = [[NSObject alloc]init];
    //取得的对象存在, 但自己不持有对象
    [obj autorelease];
    return obj;
}    

使用autorelease方法可以取得对象, 但自己不持有对象. autorelease能使对象在超出指定的生存范围时能够自动正确的释放(release).

无法释放非自己持有的对象

如果应用中释放了非自己所持有的对象就会造成崩溃, 最常见的情况就是过度释放:

id obj = [[NSObject alloc]init];
[obj release];
//下面会引起崩溃
//[obj release];

或

//取得非自己生成的对象
id obj = [NSMutableArray array];	

//此时使用release会crash
//[obj release];