ARC does not change the rule you're familiar with, garbage collection must still be enabled or disabled for the entire process.
To understand how System Preferences works, take a closer look at the flags from __objc_imageinfo
. Here are the Clang definitions for those flags:
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)
};
The 10.8+ version of System Preferences has the garbage collected flag set but not the GC-only flag. This means that it was built with -fobjc-gc and includes code to support both garbage collection and retain/release. As a result it can be run with GC either enabled or disabled via the OBJC_DISABLE_GC
environment variable. Looking at the Info.plist for System Preferences this is exactly what it does:
<key>LSEnvironment</key>
<dict>
<key>OBJC_DISABLE_GC</key>
<string>YES</string>
</dict>
With this combination System Preferences launches with garbage collection disabled, and can load preference panes without GC support and those built with both GC and retain/release support via -fobjc-gc. If the user tries to open a preference pane that requires garbage collection (built with -fobjc-gc-only) System Preferences informs the user that it needs to restart to load that pane. If permission is granted the app relaunches itself with OBJC_DISABLE_GC=NO. At this point it can load preference panes that require GC support and those built with both GC and retain/release support. If the user subsequently tries to load a preference pane without GC support the app will need to relaunch again.
So there's no GC and non-GC magic here, just a backwards-compatibility mechanism made possible by the System Preferences UI not requiring that all preference panes be loaded at the same time.