正如我们所知,X代码中的编程objective-c用于表示处理对象的手动引用计数。在此之后,引入了垃圾收集,现在已被自动引用计数(ARC)取代。
过去,我有一个用GC开发的应用程序,可以使用函数调用dlopen加载库。这要求加载库与主机应用程序的库匹配,并且还使用了GC。如果库是使用ARC构建的,则dlopen将失败。当然,这种不相容性是可以预期的。
系统偏好设置应用程序就是一个很好的例子。它使用垃圾收集: -
otool -oV /Applications/System\ Preferences.app/Contents/MacOS/System\ Preferences | tail -3
Contents of (__DATA,__objc_imageinfo) section
version 0
flags 0x2 OBJC_IMAGE_SUPPORTS_GC
直到10.7 so did the preference panes which it loads。但是,在10.8中,系统偏好设置应用程序仍然使用GC,但它加载的一些窗格不会: -
otool -oV /System/Library/PreferencePanes/Network.prefPane/Contents/MacOS/Network | tail -3
Contents of (__DATA,__objc_imageinfo) section
version 0
flags 0x0
那么,这里发生了什么? System Preferences应用程序的垃圾收集机制如何处理ARC编译的窗格?他们只是泄漏了内存,还是在下面进行某种转换?
答案 0 :(得分:2)
ARC不会更改您熟悉的规则,仍然必须为整个过程启用或禁用垃圾回收。
要了解“系统偏好设置”的工作原理,请仔细查看__objc_imageinfo
中的标记。以下是这些标志的Clang definitions:
enum ImageInfoFlags {
eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
eImageInfo_GarbageCollected = (1 << 1),
eImageInfo_GCOnly = (1 << 2),
eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
// A flag indicating that the module has no instances of a @synthesize of a
// superclass variable. <rdar://problem/6803242>
eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
eImageInfo_ImageIsSimulated = (1 << 5)
};
10.8+版本的系统偏好设置已设置垃圾收集标志,但不设置仅GC标志。这意味着它是使用-fobjc-gc构建的,并包含支持垃圾收集和保留/释放的代码。因此,可以通过OBJC_DISABLE_GC
环境变量启用或禁用GC。查看System Preferences的Info.plist,这正是它的作用:
<key>LSEnvironment</key>
<dict>
<key>OBJC_DISABLE_GC</key>
<string>YES</string>
</dict>
使用此组合系统首选项启动时禁用垃圾收集,并且可以加载没有GC支持的首选项窗格以及通过-fobjc-gc同时使用GC和保留/释放支持构建的窗格。如果用户尝试打开需要垃圾回收的首选项窗格(仅使用-fobjc-gc构建),系统首选项会通知用户需要重新启动才能加载该窗格。如果授予权限,则应用程序将重新启动OBJC_DISABLE_GC = NO。此时,它可以加载需要GC支持的首选项窗格以及使用GC和保留/释放支持构建的窗格。如果用户随后尝试加载没有GC支持的首选项窗格,则应用程序将需要重新启动。
所以这里没有GC和非GC魔法,只是系统首选项UI可以实现的向后兼容机制,不需要同时加载所有首选项窗格。
答案 1 :(得分:0)
ARC 实际上向后兼容在非ARC下编译的库和框架,因此将ARC代码与非ARC代码混合并不罕见。它的工作方式是在编译时使用一个标志来打开/关闭ARC:
-fno-objc-arc
-fobjc-arc
例如,您可以将目标设置为默认为ARC,对于非ARC的代码,您可以在该特定构建阶段切换到非ARC编译器。
显然它不仅仅是我所提到的,但至少你知道将非ARC与ARC混合是非常可能的。