OC里面的ARC

当OC出了ARC之后,有人拍手称快,有人根本不屑于看,MRC依旧用的很溜,但是随着版本的更迭,ARC越来越强壮,性能也越来越好,也有更多的人去用,那么今天就先来讲讲简单的ARC用法。

ARC,自动引用计数(Automatic Reference Counting),减轻了我们的各种release。

Apple的文档里是这么定义ARC的:

“自动引用计数(ARC)是一个编译器级的功能,它能简化Cocoa应用中对象生命周期管理(内存管理)的流程。”

先来说说引用计数:

手工管理,引用计数式的内存管理在IOS中是这样工作的:当使用alloc/init(或者其它类似方法)创建对象时,随同对象返回的,还有一个retainCount,其值为1,表明我们获得了这个对象的所有权。

NSObject *obj = [[NSObject alloc] init];
[obj release];
在对象的alloc和release之间,我们可以随意使用,这时系统是无法回收正在使用中的对象的。

或者说将对象加入到自动释放池也是类似,对象会一直存在,知道未来的某个时间我们不再需要它,才会被系统收回。

-(NSObject*) someMethod {
 NSObject *obj = [[[NSObject alloc] init] autorelease];
 return obj; // will be deallocated by autorelease pool later
}


那么现在说说ARC的工作原理

大多数的IOS程序猿都会在引用计数的问题上遇到理解障碍。ARC则是一个编译前的步骤,因为它为我们的代码自动加上了release。

ARC并不是垃圾收集,而且,引用计数也没有消失,只是变成自动而已。这里很多人都认为这是垃圾回收,其实不是,只是自动的而已。

ARC状态下

<span style="font-family: Arial, Helvetica, sans-serif;">NSObject *obj = [[NSObject alloc] init];</span>
就相当于MRC状态下的

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

如果想开启ARC,那么只需要在工程的Build Setting中设置ARC为YES,或者在项目的后面加上-fobjc-arc的编译器标识。

ARC的规则

1.对象的alloc

创建对象的方法跟以前一样,但是你一定不能调用retain/release/autorelease/retaincount,也不能通过selector调用。

2.dealloc方法

ARC会自动为你调用,一定不能直接调用dealloc。不过,如果你需要释放实例变量以外的资源,还是可以创建自定义的dealloc方法,但是这个方法里,不要调用【super  dealloc】。因为ARC会帮你调用。

3.声明的属性

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

4.C结构中的对象指针

同意禁止使用,文档里建议不要把它们放在结构了,改放到类里去,否则ARC就不认识它们了。可能会出现一些移植上的问题。

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

当我们在Core Foundation的C函数和Foundation Kit的OC方法间传递对象时,常常需要进行id和void*两个类型的互转,叫做无缝桥接(Toll Free Bridging)。

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

这一块已经比较高速了,如果不清楚CF对象是什么,也不需要太大的烦恼。

6.以@autoreleasepool代替NSAutoReleasePool

兼容ARC的代码不能再使用NSAutoReleasePool对象,而要改用@autoreleasepool{}块。一个很好的例子:

int main(int argc, char *argv[])
{
 @autoreleasepool {
   return UIApplicationMain(argc, argv, nil, NSStringFromClass([ExampleAppDelegate class]));
 }
}

7.其他

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


ARC限定符 - 声明的属性

身为程序员,习惯于作出一些决定,比如声明的是常量还是变量、本地还是全局,and so on。so 我们也要决定某个属性与其它属性的关系,我们用strong/weak来把这以关系告诉给编译器。

强引用

强引用是对某对象的引用,并且能阻止它被回收。换句话说,强引用创建了一个所有关系。在ARC之前,我们都是写成:

@property(retain) NSObject *obj;

在ARC下,我们这么写就好了:

@property(strong) NSObject *obj;
弱引用

弱引用是对某对象的引用,但不能阻止它被回收。换句话说,弱引用并不会创建所有关系。在ARC之前,我们这么写:

@property(assign) NSObject *obj;

在ARC下,我们需要这么写,以确保当前实例没有获得被引用对象的所有权(一般来说,子对象不应该拥有父对象,这时可以用弱引用)。

@property(weak) NSObject *obj;

ARC限定符 - 常规变量

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

__strong
__weak
__unsafe_unretained
__autoreleasing

一般来说,我们不需要用,新工程基本不需要用。

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

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

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

__autoreleaseing:不要与autorelease搞混,它用于通过引用传递对象,比如,通过引用传递NSError对象:[myobjcet performOperationWithError:&tmp]。


注意:我们在ARC下,@property中使用“retain”时(而不是“strong”),编译器并不会报错,而且能生存同样结果。但以后可能会变,所以还是用“strong”吧。


我该用ARC吗?

如果你是Objective-C的新手,肯定会欢迎ARC。一开始,有太多的东西要学习,有了ARC就不用担心手工计数的问题。随着你开始接触一些已有的库,就会经历一些痛苦(译者注: 目前的第三方库很多不兼容ARC),但只要习惯了将它们排除在ARC之外,就没什么问题了。

如果你不是新手,在没有ARC的年代已经玩的很high,那么可能会觉得“我干嘛要用它!”对你来说,这可能是正确的答案——就目前而言。因为,大多数流行的库都还没转到ARC下,而且ARC对Core Foundation的支持也不好。使用CF类的时候有一些限制,而且,移植代码的时候,为了让免费桥接生效,还需要加上一大堆限定符。

在我看来,目前ARC已经是可以使用的状态了。不过,除非你对它很熟悉,否则还是先用在新工程里会比较好。虽然ARC兼容iOS 4.0以上,但弱引用只在iOS 5.0以上才支持,所以现在还是不要把所有东西都移植过去(有一些相关的文章,请参考最后的“资源”一节)

至于性能方面,早前有报告指出用ARC之后速度会变快,我想可能是由于减少对自动释放的依赖的缘故。虽然这完全可以通过改进代码、更好地使用retain/release来实现,但我觉得重点在于,ARC总是会自动帮你选择最优的方法。

目前为止,还是有很多令人苦恼的东西被移到ARC,但还不是全部。在长周末后我们会离开一段时间以投入到新的项目,但是这是苹果一个“新的”推荐手段,所以你可以肯定以后的设计决策会继续强大ARC并且让大家离开使用手动的引用计数






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值