使用ARC时须要遵循的规则


若是想用ARC,必须服从一些新规则

1. 对象的Alloc/Init程序员

建立对象的方法跟之前同样,但你必定不能调用retain/release/autorelease/retainCount。也不能经过selector偷偷地调用它们: 禁止使用@selector(retain)和@selector(release)。函数

2. dealloc方法工具

ARC为自动为你调用,必定不能直接调用dealloc。不过,若是你须要释放实例变量之外的资源,仍是能够建立自定义的dealloc方法。但在这个方法里,不要调用[super dealloc]。由于ARC会帮你调。spa

3. 声明的属性指针

在ARC以前,咱们是用@property指令中的assign/retain/copy参数来告诉编译器,如何管理这些属性的内存。用了ARC以后,这些参数就做废了,改用weak/strong这两个参数。code

4. C结构中的对象指针orm

一样禁止使用。文档里建议不要把它们放在结构了,改放到类里去。不然ARC就不认识它们了。可能会出现一些移植上的问题。不过,ARC是能够以文件为单位来关闭的。参考下文的“引入不兼容ARC的代码”。对象

5. id与void*之间的临时互转内存

当咱们在Core Foundation的C函数和Foundation Kit的Objective-C方法间传递对象时,经常须要进行id和void*两个类型的互转。叫作免费桥接(Toll Free Bridging)。资源

若是使用ARC,必须在CF对象进入和脱离ARC的控制时,用提示/限定符来告知编译器。限定符有__bridge、__bridge_retain和__bridge_transfer。另外,仍须要用CFRetain和CFRelease来管理Core Foundation的对象。

这一块已经比较高深了,若是你不清楚CF对象是什么,也不须要太烦恼。


6. 以@autoreleasepool代替NSAutoReleasePool

兼容ARC的代码不能再使用NSAutoReleasePool对象,而要改用@autoreleasepool{ }块。

7. 其它

基于Zone的内存已经没了(在运行时里也没了)。不能再使用NSAllocateObject和NSDeallocateObject。


ARC限定符 - 声明的属性

身为程序员,习惯于作出一些决定,例如把某个量声明为变量仍是常量、本地仍是全局,等等。所以,在这里,咱们也要决定某个属性与其它属性的关系。咱们用strong/weak来把这一关系告诉编译器。

强引用

强引用是对某对象的引用,而且能阻止它被回收。换句话说,强引用建立了一个全部关系。在ARC以前,咱们这么写:

// Non-ARC Compliant Declaration
@property(retain) NSObject *obj;

在ARC下,咱们须要这么写,以确保当前实例得到被引用对象的全部权(主人不被回收,它也不能被回收)。

// ARC Compliant Declaration
@property(strong) NSObject *obj;

弱引用

弱引用是对某对象的引用,但不能阻止它被回收。换句话说,弱引用并不会建立全部关系。在ARC以前,咱们这么写:

// Non-ARC Compliant Declaration
@property(assign) NSObject *parentObj;

在ARC下,咱们须要这么写,以确保当前实例没有得到被引用对象的全部权(通常来讲,子对象不该该拥有父对象,这时能够用弱引用)。

// ARC Compliant Declaration
@property(weak) NSObject *parentObj;


ARC限定符 - 常规变量

上一节是说明如何管理属性。对于常规变量,则有:

__strong
__weak
__unsafe
_unretained
__autoreleasing

通常来讲,咱们不太须要使用上面这些限定符。在使用移植工具的时候可能会看到那么几个,但新工程基本上不须要。

__strong: 默认限定符,不须要显式指定。表示任何用alloc/init建立的对象在当前范围的生命期内得以保留。“当前范围”是指变量声明语句所在的两个大括号之间(方法、循环、块,等等)。

__weak: 表示对象能够随时被摧毁。只有当它被其它对象强引用时才有用。__weak变量在摧毁时,被设为nil。

__unsafe_unretained: 与__weak相似,但在摧毁时,不设为nil,保留原值(再也不指向有效的东西)。

__autoreleasing: 不要与autorelease搞混,它用于经过引用传递对象,好比,经过引用传递NSError对象: [myObject performOperationWithError: ]。