IOS 5 ARC机制 (四)
常见问题解答
ARC的机制是什么?它在那里放入retain/release函数调用?
请停止思考这些问题,把更多的精力放在下面的问题上,比如你的程序逻辑,对象的强,弱引用,对象的所属关系,可能的循环引用等问题上。
我还需要为我的类写一个dealloc函数么?
可能。
因为ARC并不自动调用malloc/free,并不自动管理像核心功能对象、文件描述符等的生命周期,所以你仍然需要在dealloc中释放它们。
你不会(实际上是不能)释放对象实例,但是你仍然需要为系统类调用[self setDelegate:nil]或其他ARC不会自动生产释放代码的情况下释放资源。
dealloc方法在ARC不是必须的,并且不许调用[super dealloc]。
ARC中会出现循环引用(retain cycles)么?
是的。
ARC自动产生retain/release函数,同时也继承了产生循环引用的机制。幸运的是,ARC很少有内存泄漏,因为在声明属性的变量的时候决定是否使用retain。
注:请搜索什么是retain cycles.
ARC下面的块代码如何工作?
块代码在ARC方式下,只能在栈上传递的方式下工作,比如在return语句中。你不用在调用Block Copy。你还是必须在为arrayWithObjects: 传入栈的时候使用[^{} copy]和其他的retain功能的函数。
有一件事情需要提到,在ARC方式下,__block NSString *S是可以使用,它不是一个野指针。使用_block __unsafe_unretained NSString *S 或者 (更好的方式) __block __weak NSString *S.
我能在雪豹(Snow Leopard)上的XCode为MAC OS X开发应用的时候使用ARC么?
不能,那个版本的Xcode4.2不支持ARC。雪豹版本没有10.7的SDK,所以在为MAC OS X开发应用的时候不能使用ARC,但是这个版本支持为iOS开发的时候使用ARC。狮子(Lion)版本的是可以的。
在支持ARC的工程中我能创建实例数组么?
是的,你可以,如下例所示:
// Note calloc() to get zero-filled memory.__strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(sizeof(SomeClass *), entries);for (int i = 0; i < entries; i++) {dynamicArray[i] = [[SomeClass alloc] init];}// When you're done, set each entry to nil to tell ARC to release the object.for (int i = 0; i < entries; i++) {dynamicArray[i] = nil;}free(dynamicArray);
这里有几点需要注意的地方:
-
你必须在某些情况下写__strong SomeClass **,因为如果你不写,缺省的是__autoreleasing SomeClass **.
-
申请的内存必须使用0填充。
-
在释放这个数组前,你必须设置每一个元素为nil(调用memset,并传入0是没有用的)。
-
你必须避免使用memcpy或realloc。
ARC慢么?
这个取决你如何衡量这个问题了,不过一般来说,这个问题的答案是“no”。下面是原文的解释,我总结的是要相信编译器在这个方面的能力。It depends on what you’re measuring, but generally “no.” The compiler efficiently eliminates many extraneousretain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.
One issue to be aware of is that the optimizer is not run in common debug configurations, so expect to see a lot more retain/release traffic at-O0 than at-Os.
在ObjC++模式,ARC能否工作?
式的,你甚至可以在类或者容器中使用strong/weak id。为了能正常工作,ARC在编译期间会在复制构造函数和析构函数中加入retain/release方面的逻辑。一个事情需要避免的就是,你不能为某些指针使用__strong,例如:
std::vector<__strong NSString*> V;
那些类不支持自动nil化的弱引用?
下面的类的实例不能使用自动nil化的弱引用
NSATSTypesetter, NSColorSpace, NSFont, NSFontManager, NSFontPanel, NSImage,NSMenuView,NSParagraphStyle,NSSimpleHorizontalTypesetter,NSTableCellView,NSTextView,NSViewController,NSWindow, andNSWindowController. 还有,OS X上的AV Foundation框架中所有类都不支持自动nil化的弱引用。
如果属性变量是这些类的实例的时候,使用assign来替代weak;作为变量,使用__unsafe_unretained来替代__weak。
此外,你也不用对NSHashTable,NSMapTable, 和NSPointerArray的实例做弱应用。
在写类似于NSCell这样使用了NSCopyOjbect的子类的时候有什么需要特别关注的地方么?
没有什么特别的,ARC会做一切事情。
我可以为每一个文件单独指定是否使用ARC么?
是的。
当你为一个旧的工程添加ARC是,编译选项-fobjc-arc对所有的文件都是有效的。你可以使用编译选项-fno-objc-arc为某个类单独禁止ARC。在target上的Build Phases 页,打开Compile Sources组,这里有一个文件列表,双击某个文件,加入-fno-objc-arc就可以为这个文件禁用ARC。
GC (Garbage Collection)是否被废弃了?
GC在10.7系统中被支持,但是强烈建议在新工程中使用ARC,对于你老的代码,你可以做一下转换,比较工作量不大。