iOS 中 NSString 與 CFStringRef 可直接強制轉換:
CFStringRef aCFString = (CFStringRef)aNSString;
NSString *aNSString = (NSString *)aCFString;
但 ARC 僅管理 Objective-C 對象,Core Foundation 對象需手動 CFRetain/CFRelease。轉換後「誰負責釋放」成為關鍵,處理不當導致洩漏或雙重釋放崩潰。
// NSString → CFStringRef
CFStringRef aCFString = (CFStringRef)[[NSString alloc] initWithFormat:@"%@", string];
// 使用後
CFRelease(aCFString);
// CFStringRef → NSString
CFStringRef aCFString = CFStringCreateWithCString(kCFAllocatorDefault, bytes, NSUTF8StringEncoding);
NSString *aNSString = (NSString *)aCFString;
// 使用後
[aNSString release];
轉換後由持有者釋放,邏輯直觀。
告訴編譯器所有權轉移意圖:
| 修飾符 | 宏等價 | 語義 |
|---|---|---|
__bridge | — | 僅類型轉換,**不改變所有權** |
__bridge_retained | CFBridgingRetain() | OC→CF,**解除 ARC 所有權**,開發者需 CFRelease |
__bridge_transfer | CFBridgingRelease() | CF→OC,**轉移所有權給 ARC**,無需手動管理 |
__bridge_retained / CFBridgingRetain()OC 對象轉 CF,ARC 放棄管理,開發者負責 CFRelease:
NSString *aNSString = [[NSString alloc] initWithFormat:@"test"];
CFStringRef aCFString = (__bridge_retained CFStringRef)aNSString;
// 等價
CFStringRef aCFString = (CFStringRef)CFBridgingRetain(aNSString);
// 必須釋放
CFRelease(aCFString);
未釋放將洩漏(Instruments 可檢測)。
__bridge_transfer / CFBridgingRelease()CF 對象轉 OC,所有權交給 ARC:
CFStringRef aCFString = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII);
NSString *aNSString = (__bridge_transfer NSString *)aCFString;
// 等價
NSString *aNSString = (NSString *)CFBridgingRelease(aCFString);
// 無需手動 release,ARC 自動管理
可用於修復上例洩漏:aNSString = (__bridge_transfer NSString *)aCFString;
__bridge(最常用)純類型轉換,所有權不變:
NSString *aNSString = [[NSString alloc] initWithFormat:@"test"];
CFStringRef aCFString = (__bridge CFStringRef)aNSString;
// 無需 CFRelease
CFRelease
CFStringRef aCFString = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII);
NSString *aNSString = (__bridge NSString *)aCFString;
// 使用後
CFRelease(aCFString);
| 場景 | 推薦修飾符 | 釋放責任 |
|---|---|---|
| OC→CF,臨時借用,生命週期由 OC 控制 | __bridge | ARC |
| OC→CF,CF 需長期持有,OC 不再持有 | __bridge_retained | 開發者 (CFRelease) |
| CF→OC,OC 接管生命週期 | __bridge_transfer | ARC |
| CF→OC,OC 僅臨時使用,CF 仍持有 | __bridge | 開發者 (CFRelease) |