Objective-C 初阶 —— __bridge & __bridge_retained & __bridge_transfer

一、ARC & MRC

1、ARC

ARC 就是自动引用计数. 每当一块内存被一个强引用(指针)指着, 这块内存的引用计数自动 +1, 而每当一个强引用(指针)被销毁或置空后, 这块内存的引用计数会自动 -1.

当然, 无论是 ARC 还是 MRC, 只要这块内存的引用计数为 0, 那么这块内存就会被自动释放.

2、MRC

MRC 就是手动引用计数. 就是指针(引用)的指与不指都不会影响内存的引用计数. 只有当你每调一次 retain / CFRetain, 这块内存的引用计数才会 +1; 每调一次 release / CFRelease, 这块内存的引用计数才会 -1.

当然, 只有当这块内存的总引用计数 (ARC 侧 + MRC 侧) 为 0 时, 这块内存才会被释放.

二、__bridge & __bridge_retained & __bridge_transfer

1、__bridge

__bridge 只会基于 Core Foundation 的引用创建一个 Foundation 里的引用, 或基于 Foundation 引用创建一个 Core Foundation 的引用; 并不会自动帮你调 CFRetain 或 CFRelease.

但需要注意的是: 如果你在 Core Foundation 侧通过 __bridge 创建一个 Foundation 侧的引用, 由于这块内存被 Foundation 侧的引用指着, 而 Foundation 是遵循 ARC 的, 因此 ARC 侧会增加一个引用计数, 于是这块内存总的引用计数 (CoreFoundation/MRC 侧 + Foundation/ARC 侧) 就会 +1.

2、__bridge_retained

__bridge_retained 会基于 Foundation 的引用创建一个 Core Foundation 的引用, 然后自动帮你调一次 CFRetain() 函数.

因此 __bridge_retained 会自动为 MRC 侧增加一个引用计数, 导致这块内存的总引用计数 (CoreFoundation/MRC 侧 + Foundation/ARC 侧) +1.

3、__bridge_transfer

__bridge_transfer 会基于 CoreFoundation 侧的引用创建一个 Foundation 侧的引用, 然后再自动帮你调一次 CFRelease() 函数.

因此 __bridge_transfer 会自动为 CoreFoundation/MRC 侧减少一个引用计数; 同时因为 Foundation 侧遵循 ARC, 所以 ARC 侧又会增加一个引用计数, 因此这块内存总的引用计数 (CoreFoundation/MRC 侧 + Foundation/ARC 侧) 是没变的.

三、Demo 展示

如果大家想看更直观的对比, 可以在 command line tool 拷贝下面的代码, 看看引用计数的变化.

objectivec 复制代码
//
//  main.m
//  toll-free bridge
//
//  Created by chuanzhima on 2025/10/26.
//

#import <Foundation/Foundation.h>

#define PRINT_RC(obj, name) NSLog(@"[RC] %@ (%p): %ld", name, obj, CFGetRetainCount((__bridge CFTypeRef)obj))

void demo_bridge_retained(void) {
    NSLog(@"\n--- Demo 1: __bridge_retained ---");

    // 1️⃣ ARC 创建一个堆对象
    NSMutableString *str_arc = [[NSMutableString alloc] initWithString:@"Hello Retained"];
    PRINT_RC(str_arc, @"初始 str_arc");
    // 预期 RC = 1

    // 2️⃣ __bridge_retained:增加 RC,ARC 不再管理
    CFStringRef cfStr = (__bridge_retained CFStringRef)str_arc;
    PRINT_RC((__bridge id)cfStr, @"__bridge_retained 之后");

    // 3️⃣ ARC 侧清空引用
    str_arc = nil;
    NSLog(@"ARC 清空 str_arc");
    PRINT_RC((__bridge id)cfStr, @"str_arc 置 nil 后");

    // 4️⃣ CF 侧转换为 F 侧
    NSMutableString *str_arc1 = (__bridge NSMutableString *)cfStr;
    NSLog(@"CF 侧转换为 F 侧");
    PRINT_RC(str_arc1, @"CF 侧转换为 F 侧后");
    str_arc1 = nil;
    PRINT_RC((__bridge id)cfStr, @"str_arc1 置空后");

    // 5️⃣ 手动释放 CF 持有的引用
    CFRelease(cfStr);
    NSLog(@"手动 CFRelease 后,对象应释放\n");
}

void demo_bridge_transfer(void) {
    NSLog(@"\n--- Demo 2: __bridge_transfer ---");

    // 1️⃣ CF 创建对象(手动管理)
    CFMutableStringRef cfStr = CFStringCreateMutableCopy(NULL, 0, CFSTR("Hello Transfer"));
    PRINT_RC((__bridge id)cfStr, @"初始 cfStr");

    // 2️⃣ __bridge_transfer:ARC 接管并 CFRelease 一次
    NSString *str_arc = (__bridge_transfer NSString *)cfStr;
    PRINT_RC(str_arc, @"__bridge_transfer 之后");

    // 3️⃣ 作用域结束,ARC 自动释放 str_arc
    NSLog(@"str_arc 即将离开作用域 (ARC 将自动释放)\n");
}

void demo_bridge(void) {
    NSLog(@"\n--- Demo 3: __bridge ---");

    // 1️⃣ CF 创建对象(手动管理)
    CFMutableStringRef cfStr = CFStringCreateMutableCopy(NULL, 0, CFSTR("Hello Bridge"));
    PRINT_RC((__bridge id)cfStr, @"初始 cfStr");

    // 2️⃣ __bridge:仅类型转换,不改变所有权
    NSString *str_arc = (__bridge NSString *)cfStr;
    PRINT_RC(str_arc, @"__bridge 转换后");

    // 3️⃣ ARC 不会负责释放,需要手动 CFRelease
    CFRelease(cfStr);
    NSLog(@"手动 CFRelease 完成 (ARC 不参与)\n");
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        demo_bridge_retained();
        demo_bridge_transfer();
        demo_bridge();
    }
    return 0;
}
相关推荐
笑尘pyrotechnic4 小时前
【OC】UIKit常用组件适配iOS 26
macos·ios·cocoa
ii_best9 小时前
按键精灵安卓/iOS脚本辅助,OpenCV实现自动化高效率工具
ios·自动化·编辑器·安卓
蒲公英少年带我飞9 小时前
iOS底层原理:Method Swizzling原理和注意事项
ios
蒲公英少年带我飞9 小时前
iOS底层原理:KVC分析
ios
2501_9159214310 小时前
iOS混淆与IPA加固全流程(iOS混淆 IPA加固 Ipa Guard实战)
android·ios·小程序·https·uni-app·iphone·webview
游戏开发爱好者810 小时前
iOS 26 App 开发阶段性能优化 从多工具协作到数据驱动的实战体系
android·ios·小程序·uni-app·iphone·webview·1024程序员节
2501_9151063210 小时前
深入剖析 iOS 26 系统流畅度,多工具协同监控与性能优化实践
android·ios·性能优化·小程序·uni-app·cocoa·iphone
蒲公英少年带我飞10 小时前
iOS底层原理:OC对象底层探索之alloc初探
ios