ARC在工程上的相关设置

Automatic Reference Counting (ARC) 是一个编译期的技术,利用此技术可以

简化Objective-C编程在内存管理方面的工作量。

ARC在Xcode4.2中引入,在Mac OS X v10.6,v10.7 (64位应用),iOS 4,iOS 5中支持,Xcode4.1中不支持这个技术。

虽然ARC是与iOS5一同推出,但是由于ARC的实现机制是在编译期完成,所以使用ARC之后App仍然可以支持iOS4.3。

稍微需要注意的是,如果要在ARC开启的情况下支持iOS4.3,需要将weak关键字换成 __unsafe_unretained,

另外还有一些细节需要处理。

如下图就是Xcode集成的将非ARC工程转换成ARC工程的工具。

首先,ARC是LLVM3.0编译器的特性,而老的工程特别是Xcode3时代的工程的默认编译器很可能是GCC或者LLVM-GCC,因此第一步就是确认编译器是否正确。在Project设置面板,选择target,在Build Settings中将Compiler for C/C++/Objective-C选为Apple LLVM compiler 3.0或以上。为了确保之后转换的顺利,在这里我个人建议最好把Treat Warnings as Errors和 Run Static Analyzer都打开,确保在改变编译器后代码依旧没有警告或者内存问题。

在创建工程的时候,我们可以指定工程是否使用ARC技术,如下图

 

选中表示支持ARC,

如果是你拿到的工程,那么可以通过设置来改变,如下图所示

 

如果不容易找到,可以在设置的右上角搜索框输入Automatic做一个过滤。

另外,为了兼容第三方的非ARC开源库,你也可以在工程中随意使用编译参数:-fno-objc-arc ,

这个参数允许对部分文件关闭ARC。

直接在targets->build phases中修改compiler Flags,是否支持arc。

添加:-fobjc-arc,就可以让旧项目支持arc。如果想让原来支持arc的不使用arc则添加-fno-objc-arc

如果只想对某个.m文件不适应ARC,可以只针对该类文件加上

-fno-objc-arc 编译,如下图。

同样你可以添加编译标记-fobjc-arc来让你的工程支持ARC。

 

ARC的工程,转换规则包括:

        1.去掉所有的retain,release,autorelease

        2.把NSAutoRelease替换成@autoreleasepool{}块

        3.把assign的属性变为weak

使用ARC的一些强制规定

        1.不能直接调用dealloc方法,不能调用retain,release,autorelease,reraubCount方法,

        包括@selector(retain)的方式也不行


        2.截图租户事故宣布dealloc方法来管理一些资源,但不能用来释放实例变量,

       也不能在dealloc方法里面去掉[super dealloc]方法,在ARC下父类的dealloc同样由编译器来自动完成

        3.Core Foundation类型的对象任然可以用CFRetain,CFRelease这些方法

        4.不能在使用NSAllocateObject和NSDeallocateObject对象

        5.不能在c结构体中使用对象指针,如果有类似功能可以创建一个Objective-c类来管理这些对象

        6.在id和void *之间没有简便的转换方法,同样在Objective-c和core Foundation

        类型之间的转换都需要使用编译器制定的转换函数

        7.不能再使用NSAutoreleasePool对象,ARC提供了@autoreleasepool块来代替它,这样更加有效率

        8.不能使用内存存储区(不能再使用NSZone)

        9.不能以new为开头给一个属性命名

        10.声明outlet时一般应当使用weak,除了对StoryBoard 这样nib中间的顶层对象要用strong

        11.weak 相当于老版本的assign,strong相当于retain

 

  • strong. 这是以前的 “retain” 的一个代号。 strong 属性将会成为它所指对象的所有者。
  • weak. 这个属性表示弱引用指针。 当它指向的对象被销毁时,它会被自动的设置成 nil。 记住,在 outlet 上使用它
  • unsafe_unretained. 这和以前的 “assign” 等同。 你只需要在一些例外的情况下会应道它,并且当你在给 iOS 应用时,后面会讲到更多。
  • copy. 这个和之前是一样的。 它创建一个对象的拷贝,并且创建一个强引用关系。
  • assign. 你不再允许在对象上用这个修饰符, 但你仍然能在简单类型的值,比如 BOOL,int 和 float 中用到它。

 使用关键字”strong”进行标志,它意味着只要该指针指向某个对象,那么这个对象就不会被销毁。

反过来说,ARC的一个基本规则即使,只要某个对象被任一strong指针指向,那么它将不会被销毁。

如果对象没有被任何strong指针指向,那么就将被销毁。在默认情况下,所有的实例变量和局部变量

都是strong类型的。可以说strong类型的指针在行为上和MRC时代retain的property是比较相似的。

 

既然有”strong”,那肯定有”weak”。

weak类型的指针也可以指向对象,但是并不会持有该对象。

根据之前提到的“只要某个对象被任一strong指针指向,那么它将不会被销毁。如果对象没有被任何strong指针

指向,那么就将被销毁”原则,此时指向对象的指针中没有strong类型的指针,对象将被销毁。同时,在ARC机制

作用下,所有指向这个对象的weak指针将被置为nil。这个特性相当有用,相信无数的开发者都曾经被指针指向

已释放对象所造成的EXC_BAD_ACCESS困扰过,使用ARC以后,不论是strong还是weak类型的指针,

都不再会指向一个dealloced的对象,从根源上解决了意外释放导致的crash。

不过在大部分情况下,weak类型的指针可能并不会很常用。比较常见的用法是在两个对象间存在包含关系时:

对象1有一个strong指针指向对象2,并持有它,而对象2中只有一个weak指针指回对象1,从而避免了循环持有。

一个常见的例子就是oc中常见的delegate设计模式,viewController中有一个strong指针指向它所负责

管理的UITableView,而UITableView中的dataSource和delegate指针都是指向viewController的weak指针。

可以说,weak指针的行为和MRC时代的assign有一些相似点,但是考虑到weak指针更聪明些(会自动指向nil),

因此还是有所不同的。 

如图参考

注意类似下面的代码似乎是没有什么意义的: 

__weak NSString *str = [[NSString alloc] initWithFormat:…]; 
NSLog(@"%@",str); //输出是"(null)"

 

由于str是weak,它不会持有alloc出来的NSString对象,因此这个对象由于没有有效的strong指针指向,

所以在生成的同时就被销毁了。如果我们在Xcode中写了上面的代码,我们应该会得到一个警告,因为

无论何时这种情况似乎都是不太可能出现的。你可以把weak换成strong来消除警告,或者直接前面

什么都不写,因为ARC中默认的指针类型就是strong。

property也可以用strong或weak来标记,简单地把原来写retain和assign的地方替换成strong或者

weak就可以了。

@property (nonatomic, strong) NSString *firstName; 
@property (nonatomic, weak) id  delegate;

 

详细参考苹果的官方文档,在xcode4.2以上版本中,在控制面板Organizer中搜索ARC

 

参考

http://www.onevcat.com/2012/06/arc-hand-by-hand/

http://www.lanrenios.com/tutorials/all/2012/1024/221.html

 

 

posted on 2013-04-16 14:32  一梦浮生2012  阅读(648)  评论(0编辑  收藏  举报