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