其他分享
首页 > 其他分享> > [iOS]-引用计数基础

[iOS]-引用计数基础

作者:互联网

什么是自动引用计数

自动引用计数(ARC,Automatic Reference Counting)是指内存管理中对引用采取自动计数的技术,苹果官方的说明如下
在Objective-C中采用Automatic Reference Counting (ARC)机制,让编译器来进行内存管理。在新一代Apple LLVM编译器中设置ARC为有效状态,就无需再次键入retain或者release代码,者在降低程序崩溃、内存泄漏等风险的同时,很大程度上减少了开发程序的工作量。编译器完全清楚目标对象,并能立即释放哪些不再被使用的对象。如此一来,应用程序将具有可预测性,且能流畅运行,速度也将大幅提升。

关于ARC技术,最重要的还是下面这一点:

在LLVM编译器中设置ARC为有效状态,就无需再次键入retain或者是release代码。

满足以下条件时就无需手工输入retain和release代码了。

在这些条件下编译源代码时,编译器将自动进行内存管理,下面我们来了解一下如何用代码实现手工内存管理。

引用计数的内存管理

下图非常清晰地表达了引用计数的整体过程的逻辑:
在这里插入图片描述

内存管理的思考方式

思考方式如下:

对象操作与Objective-C方法的对应如下表

对象操作Objective-C 方法
生成并持有对象alloc/new/copy/mutableCopy 等方法
持有对象retain 方法
释放对象release 方法
废弃对象dealloc 方法

这些有关Objective-C 内存挂你的方法,实际上不包括在该语言中,而是包含在Cocoa框架中用于OS X、iOS应用开发。Cocoa框架中Foundation框架类库的NSObject类担负内存管理的职责。

自己生成的对象,自己持有

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

自己生成并持有对象的源代码如下:(我们先使用alloc方法)

//自己生成并持有对象

id obj = [[NSObject alloc] init];

//此时自己持有对象

使用NSObject类的alloc类方法就能自己生成并持有对象。指向生成并持有对象的指针被赋给变量obj。另外,使用如下new类方法也能生成并持有对象,且效果与alloc方法的结果完全一致

//自己生成并持有对象

id obj = [NSObject new];

//自己持有对象

根据上述的“使用以下名称开头的方法名”,下列名称也意味着自己生成并持有对象:

但是对于以下名称,即使用alloc/new/copy/mutableCopy 名称开头,却并不属于同一类别的方法(即就是加上后缀形成其他单词)。

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

用alloc/new/copy/mutableCopy以外的方法取得的对象,因为非自己生成并持有,所以自己不是该对象的持有者。这里我们用NSMutableArray类的array类方法来尝试:

//取得非自己生成并持有的对象

id obj = [NSMutableArray array];

//取得的对象存在,单自己不持有对象

源代码中,NSMutableArray类对象被赋给变量obj,但变量obj自己并不持有该对象。使用retain方法可以持有对象。

//取得非自己生成并持有的对象

id obj = [NSMutableArray array];

//取得的对象存在,单自己不持有对象

[obj retain];

//自己持有对象

通过retain方法,非自己生成的对象跟用alloc/new/copy/mutableCopy方法生成并持有的对象一样,成为了自己所持有的。

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

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

//自己生成并持有对象

id obj = [[NSObject alloc] init];

//自己持有对象

[obj release];

//释放对象
//指向对象的指针仍然被保留在变量obj中,似乎可以访问,但对象一经释放绝不可访问,否则程序就会报错。

如此,用过alloc方法由自己生成并持有的对象就通过release方法释放了。自己生成而非自己所持有的对象,若用retain方法变为自己持有,也同样可以用release方法释放

//取得非自己生成并持有的对象

id obj = [NSMutableArray array];

//取得的对象存在,但自己不持有对象

[obj retain];

//自己持有对象

[obj release];

//释放对象
//对象不可再被访问

用alloc/new/copy/mutableCopy方法生成并持有的对象,或者用retain方法持有的对象,一旦不再需要,务必要用release方法进行释放。

如果要用某个方法生成对象,并将其返还给该方法的调用方,它的源代码如下:

- (id) allocObject {
	//自己生成并持有对象

	id obj = [[NSObject alloc] init];
	
	//自己持有对象

	return obj;
}
//取得非自己生成并持有的对象

id objFirst = [objZero allocObject];

//自己持有对象

如上面两例所示,原封不动地返回用alloc方法生成并持有的对象,就能让调用方也持有该对象。因此,allocObject方法也就意味着“自己生成并持有对象”。

那么,调用[NSMutableArray array]方法使取得的对象存在,但自己不持有对象,又是怎样实现的,我们可以写一个object方法来表示一下:

- (id) object {
	id obj = [[NSObject alloc] init];
	
	//自己持有对象

	[obj autorelease];
	
	//取得的对象存在,但自己不持有对象

	return obj;
}

上面我们使用了autorelease方法,用该方法可以使取得的对象存在,但自己不持有对象。autorelease提供这样的功能,使对象在超出指定的生存范围时能够自动并正确的释放(调用release方法)。

使用NSMutableArray类的array类方法等可以取得谁都不持有的对象,这些方法都是通过autorelease方法而实现的。

id objFirst = [objZero object];

//取得的对象存在,但自己不持有对象

当然,也能够通过retain方法将调用autorelease方法取得的对象变为自己持有。

id objFirst = [objZero object];

//取得的对象存在,但自己不持有对象

[objFirst retain];

//自己持有对象

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

对于用alloc/new/copy/mutableCopy方法生成并持有的对象,或是用retain方法持有的对象,由于持有者是自己,所以在不需要该对象是需要将其释放。而由此外所得到的对象绝对不能释放,若在应用程序中释放了非自己所持有的对象就会造成崩溃。例如自己生成并持有对象后,在释放完不再需要的对象之后再次释放。

// 自己生成并持有对象

id obj = [[NSObject alloc] init];

//自己持有对象

[obj release];

//对象已释放

[obj release];

//释放之后再次释放已非自己持有的对象,应用程序崩溃
//崩溃情况:再度废弃已经废弃了的对象时崩溃

或者在“取得的对象存在,但自己不持有对象”时释放

id objFirst = [objZero object];

//取得的对象存在,但自己不持有对象

[objFirst release];

//释放了非自己持有的对象,这肯定会导致应用程序崩溃。

以上例子表明,释放非自己持有的对象会造成程序崩溃,因此不可以去释放非自己持有的对象。

标签:obj,对象,iOS,自己,生成,持有,计数,引用,方法
来源: https://blog.csdn.net/m0_52192682/article/details/120442769