【iOS开发】—— 自动引用计数初步学习

什么是自动引用计数?

==是指内存管理中对引用采取自动计数的技术。==以下是摘自苹果的官方说明:

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

内存管理/引用计数

计数
引用计数的内存管理:
请添加图片描述

内存管理的思考方式

引用计数式内存管理方式的思考:

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

对象操作与OC方法的对应:

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

以上有关Objective-C的内存管理方法,实际上不包括在该语言中,而是包含在Cocoa框架中用于OS X、iOS应用开发。Cocoa框架中Foundation框架类库的NSObject类担负内存管理的职责。
Objective-C内存管理中的alloc/retain/release/dealloc方法分别指代NSObject类的alloc类方法、retain实例方法、release实例方法和dealloc实例方法。

请添加图片描述

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

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

  • alloc
  • new
  • copy
  • mutableCopy

alloc类方法和new类方法

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

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

使用NSObjec类的alloc类方法就能使自己生成并持有对象。指向生成并持有对象的指针被赋给变量obj。使用new类方法也能生成并持有对象。

copy
copy方法利用基于NSCopying方法约定,由各类实现的copyWithZone:方法生成并持有对象的副本。与copy方法类似,mu tableCopy方法利用基于NSMutableCopying方法约定,由各类实现的mutableCopyWithZone:方法生成并持有对象。两者的区别是:copy方法生成不可更别的对象,mutableCopy则反之。用这些方法生成的对象,虽然是对象的副本,但同alloc、new方法一样,在“自己生成并持有对象”这点上没有改变。
另外根据上述“使用以下名称开头的方法名”,下列名称也以为着自己生成并持有对象:

  • allocMyObject
  • newThatObject
  • copyThis
  • mutableCopyYourObject

但是对于以下名称,即使使用了alloc/new/copy/mutableCopy名称开头,并不属于同一类别的方法。

  • allocate
  • newer
  • copying
  • mutableCopyed

非自己生成的对象,自己也能持有
用上述项目之外的方法取得的对象,即用alloc/new/copy/mutableCopy以外的方法取得的对象,因为非自己生成并持有,所以自己不是该对象的持有者。

//取得非自己生成并持有的对象
id obj = [[NSMutableArray alloc] init];
//取得的对象存在,但自己不持有对象

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

//取得非自己生成并持有的对象
id obj = [[NSMutableArray alloc] init];
//取得的对象存在,但自己不持有对象
[obj retain];
//自己持有对象

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

//自己生成并持有对象

id obj = [[NSObject alloc] init];

//自己持有对象
[obj release];

/*
指向对象的指针仍然被保存在变量obj中,貌似能够访问,但对象一经释放绝对不可以访问。
*/

无论是通过alloc等方法自己生成并持有的对象;还是自己生成而非自己所持有的对象,用retain方法变为自己持有;都可以用release方法释放。
切记:对象一旦不再需要,一定一定要用release方法进行释放。

如果要用某个方法生成对象,并将其返还给该方法的调用方,那么它的源代码是怎样的呢?

- (id)allocObject {
    
    
    /*自己生成并持有的对象*/
    id obj = [[NSObject alloc] init];
    
    return obj;
}

原封不动的返回用alloc方法生成并持有的对象,就能让调用方也持有该对象。

id obj1 = [obj0 allocObject];

那么调用[NSMutableArray array] 方法使得的对象存在,但自己不持有对象,又是如何实现呢?根据以上命名规则,不能使用以alloc/new/copy/mutableCopy开头的方法名,因此要使用object这个方法名。

- (id)object {
    
    
    id obj = [[NSObject alloc] init];
    
    [obj autorelease];
    
    return obj;
}

上例中,使用了autorelease方法,可以使取得的对象存在,但自己不持有对象。autorelease提供这样的功能,是对象在超出指定的生存范围时能够自动并正确地释放(release方法)如图。请添加图片描述

使用NSMutableArray类的array类方法等可以取得谁都不持有的对象,这些方法都是通过autorelease而实现的。此外,根据上文的命名规则,这些用来取得谁都不持有的对象的方法名不能以alloc\new\copy\mutableCopy开头,这点得注意。
retain方法将调用autorelease方法取得的对象变为自己持有。
无法释放非自己持有的对象
对于用alloc/new/copy/mutableCopy方法生成并持有的对象,或是用retain方法持有的对象,由于持有者是自己,所以在不需要该对象时需要将其释放,而由此之外所得到的对象绝对不能释放。倘若在应用程序中释放了非自己所持有的对象就会造成崩溃。
例如:自己在生成并持有对象后,在释放完不再需要的对象之后再次释放。

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

//自己持有对象

[obj release];

//对象已释放 

/*
释放之后再次释放已非自己持有的对象!
应用程序崩溃!

崩溃情况:
再度废弃已经废弃了的对象时崩溃
访问已经废弃的对象时崩溃
*/

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

id obj1 = [obj0 object];

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

[obj1 release];

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

以上这些例子所示,释放非自己持有的对象会造成程序崩溃。因此绝对不要去释放非自己持有的对象。

Guess you like

Origin blog.csdn.net/weixin_50990189/article/details/120442434