Toll-Free Bridging 和 Unmanaged

有经验的读者看到这章的标题就能知道我们要谈论的是 Core Foundation。在 Swift 中对于 Core Foundation (以及其他一系列 Core 开头的框架) 在内存管理进行了一系列简化,大大降低了与这些 Core Foundation (以下简称 CF ) API 打交道的复杂程度。

首先值得一提的是对于 Cocoa 中 Toll-Free Bridging 的处理。Cocoa 框架中的大部分 NS 开头的类其实在 CF 中都有对应的类型存在,可以说 NS 只是对 CF 在更高层面的一个封装。比如 NSURL 和它在 CF 中的 CFURLRef 内存结构其实是同样的,而 NSString 则对应着 CFStringRef。

因为在 Objective-C 中 ARC 负责的只是 NSObject 的自动引用计数,因此对于 CF 对象无法进行内存管理。我们在把对象在 NS 和 CF 之间进行转换时,需要向编译器说明是否需要转移内存的管理权。对于不涉及到内存管理转换的情况,在 Objective-C 中我们就直接在转换的时候加上 __bridge 来进行说明,表示内存管理权不变。例如有一个 API 需要 CFURLRef,而我们有一个 ARC 管理的 NSURL 对象的话,这样来完成类型转换:

NSURL *fileURL = [NSURL URLWithString:@”SomeURL”]; SystemSoundID theSoundID; //OSStatus AudioServicesCreateSystemSoundID(CFURLRef inFileURL, // SystemSoundID *outSystemSoundID); OSStatus error = AudioServicesCreateSystemSoundID( (__bridge CFURLRef)fileURL, &theSoundID);

而在 Swift 中,这样的转换可以直接省掉了,上面的代码可以写为下面的形式,简单了许多:

import AudioToolbox let fileURL = NSURL(string: “SomeURL”) var theSoundID: SystemSoundID = 0 //AudioServicesCreateSystemSoundID(inFileURL: CFURL, // _ outSystemSoundID: UnsafeMutablePointer<SystemSoundID>) -> OSStatus AudioServicesCreateSystemSoundID(fileURL!, &theSoundID)