OC 對象(`NSString*` 等)與 CF 對象(`CFStringRef` 等)**內存佈局兼容**,可直接強轉指針。但 **ARC 僅管理 OC 對象**,CF 對象需手動 `CFRetain/CFRelease`。轉換時必須明確**所有權轉移**,否則洩漏或雙重釋放崩潰。
| 修飾符 | 宏函數 | 所有權變化 | 適用場景 |
|---|---|---|---|
| __bridge | — | **不轉移**,原所有者保持 | 臨時借用、跨 API 傳參 |
| __bridge_retained | CFBridgingRetain() | **OC → CF**,ARC 放棄,調用者負責 CFRelease | OC 對象轉 CF 長期持有 |
| __bridge_transfer | CFBridgingRelease() | **CF → OC**,ARC 接管,調用者無需釋放 | CF 創建函數返回值轉 OC |
NSString *nsStr = @"hello"; CFStringRef cfStr = (__bridge CFStringRef)nsStr; // 使用 cfStr 調用 CF API // nsStr 仍由 ARC 管理,無需 CFRelease
NSString *nsStr = [[NSString alloc] initWithFormat:@"test"]; CFStringRef cfStr = (__bridge_retained CFStringRef)nsStr; // ARC 放棄 // ... 長期持有 cfStr ... CFRelease(cfStr); // 必須手動釋放,否則洩漏
等價宏:`CFStringRef cfStr = (CFStringRef)CFBridgingRetain(nsStr);`
CFStringRef cfStr = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII); NSString *nsStr = (__bridge_transfer NSString *)cfStr; // ARC 接管 // nsStr 現在由 ARC 管理,無需 CFRelease // 若此處不轉移,需手動 CFRelease(cfStr)
等價宏:`NSString *nsStr = (NSString *)CFBridgingRelease(cfStr);`
CFStringRef cfStr = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII); NSString *nsStr = (__bridge NSString *)cfStr; // 不轉移所有權 // 使用 nsStr... CFRelease(cfStr); // 創建者負責釋放
// 錯誤:OC→CF 用 __bridge 但未 CFRelease CFStringRef cf = (__bridge CFStringRef)[[NSString alloc] initWithString:@"leak"]; // cf 指向的對象無人釋放 → Leak // 正確:用 __bridge_retained 或 緊接 CFBridgingRelease CFStringRef cf2 = (__bridge_retained CFStringRef)[[NSString alloc] initWithString:@"ok"]; CFRelease(cf2); // 平衡
OC/CF 互轉核心是**所有權轉移契約**。`__bridge`(借用)、`__bridge_retained`(轉出)、`__bridge_transfer`(轉入)三者覆蓋所有場景。牢記:**Create 規則適用於 CF 創建函數,ARC 接管需 `__bridge_transfer`**。規範使用三大橋接,消除跨運行時內存管理隱患。