ARC实践

Posted syd_programming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARC实践相关的知识,希望对你有一定的参考价值。

一. 什么是引用计数


Objective-C中对对象的内存管理可以用生成、持有、释放、废弃4个词来表示,其中生成就是alloc/new/copy/mutableCopy等方法,持有对象 通过retain来实现,释放对象是release操作,废弃对象是dealloc操作。当对象生成的同时自然也持有该对象。


1. 自己生成并持有对象:

// 生成并持有对象
id obj = [[NSObject alloc] init];
// 或者
id obj = [NSObject new];


不光是这几个方法,凡是以alloc/new/copy/mutableCopy开头的方法都是持有自己。


2. 持有非自己生成的对象:

// 取得对象
id obj = [NSMutableArray array];
// 持有对象
[obj retain];

在这里,array方法返回一个谁都不持有的对象,它的实现可能是这样:

-(id) array

    // 创建并持有对象
    id obj = [[NSMutabelArray alloc] init];
    // 通过autorelease不持有对象
    [obj autorelease];
    return obj;


在该实现中,通过autorelease方法不持有对象。

3. 持有的对象一旦不再需要就要释放:

[obj release];

这里需要注意,只有自己持有该对象才能释放,释放自己没有持有的对象或者已经释放了的对象会引起程序崩溃。


二. autorelease

Autorelease的使用方法如下:

1. 生成NSAutoreleasePool对象

2. 调用对象的autorelease方法

3. 废弃NSAutorelease对象

autorelease有点像C语言的作用域,对于调用了release方法的对象,在废弃NSAutoreleasePool对象时,都将调用release方法。


NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
id obj = [[NSObject alloc]init];
[obj autorelease];
[pool drain];


普通变量,使用alloc,new ,copy创建的对象要么加上autorelease,要么在块结束的时候release.
在类和类的方法中定义的变量要么使用autorelease,要么在 类的dealloc方法 中release它们。
除了alloc、new或copy之外的方法创建的对象都自动声明了autorelease。

三. 理解strong和weak

1. strong指针

NSString* str = self.label.text;

如果此时self.label.text的值是"Test Label"的话,这行代码将使得self.label.text和str 都持有这个字符串。

如果再执行

self.label.text = @"another label";
此时str继续持有"Test Label"这个字符串,而self.label.text将持有"another label"这个字符串。

如果此时str被设置为另外一个值,或者超出了它的作用域,"Test Label"将不会被任何对象持有,它将被释放。


2. weak指针


self.label.text = @"Test Label";
weak NSString* str = self.label.text;

 

此时str将不持有"Test Label"字符串,该字符串仅被self.label.text持有。

self.label.text = @"another label";
这行代码后,@"Test Label"将不被任何对象持有,将被释放,此时str将为nil.

用weak指针指向新创建的对象将导致该对象被立即释放

id __weak obj = [[NSString alloc] init];

由于新创建的对象没有被任何对象持有,因此将立即释放。


四. ARC实践指南:

1. 原则上所有的实例变量和局部变量都应该是strong的,但对一些UI的property应该使用weak,由于它是被UIWindow所持有的,因此源码中它应该是weak的。具体一点:IBOutlet可以为weak,NSString为copy,Delegate一般为weak,其他的看情况。一般来说,类“内部”的属性设置为strong,类“外部”的属性设置为weak。说到底就是一个归属权的问题。小心出现循环引用导致内存无法释放。

2. 通过weak指针可以解决retain循环问题,即父对象拥有子对象,但子对象不拥有父对象,即子对象拥有一个指向父对象的weak指针。


五. 理解关键字 copy, assign, retain

1. 在属性中加copy,意味着建立一个新对象,这样新旧对象的retainCount都是1。

2. assign可以理解为别名,并不增加retainCount,因此适用于基础数据类型和C数据类型。

3. retain即增加计数,适用于NSObject其他子类。

详细可参见 copy, retain, assign , readonly , readwrite,strong,weak,nonatomic整理





以上是关于ARC实践的主要内容,如果未能解决你的问题,请参考以下文章

Bugly干货分享iOS内存管理:从MRC到ARC实践

Bugly干货分享iOS内存管理:从MRC到ARC实践

iOS 5 最佳实践(发布/保留?)

微服务实践——Docker与服务发现

转:在支持ARC工程中编译不支持ARC的文件

XCode 4.6 中的 Mogenerator 和 ARC