美文网首页
《Objective-C高级编程 iOS与OS X多线程与内存管

《Objective-C高级编程 iOS与OS X多线程与内存管

作者: 我才是臭吉吉 | 来源:发表于2019-01-06 16:10 被阅读9次

    内存管理篇: 5.ARC的规则补充

    1. ARC的方法命名

    我们都知道,在内存管理的思考方式中,当方法命名以“alloc、new、copy、mutableCopy”开头或直接命名时,返回对象(必须返回对象)的内存由接收方进行管理。这种方式在ARC中同样适用。

    在ARC环境下,以init或init开头的方法,也需要遵循此规则。且init的方法规定更为严格:

    • 必须返回id或类型的对象
    • 必须是实例方法

    1. OC对象(这里代指Foundation框架中类的对象)不能直接作为C数据结构的成员。

    原因:ARC为OC语言编译器特性,不支持对C语言进行内存管理(最新的iOS 12中,好像已经支持此特性了,LLVM真强大。。。)

    对于需要作为成员的OC对象,解决方法:

    • 使用“__unsafe_unretained”进行所有权修饰,显示声明并告知编译器不要对其进行内存管理;
    • 通过“__bridge”将OC对象转换为(void *)指针。

    1. 显示转换“id”与“void *”

    对象与C指针之间是通过“__bridge”关键字进行转换,主要分为三种方式:

    • __bridge
    • __bridge_retained
    • __bridge_transfer
    • __bridge:

    直接转换,忽略ARC内存管理,与添加__unsafe_unretained效果类似:

    id obj = [[NSObject alloc] init];
    // 转换为c指针
    void *p = (__bridge void *)obj;
    // 转换为OC对象
    id obj2 = (__bridge id)p;
    
    • __bridge_retained:

    意为“转换后进行保留”,接收方对其自动强引用(同时掌握所有权),与__strong的retain效果类似:

    void *p = 0;
    {
        id obj = [[NSObject alloc] init];
        // 转换为c指针
        p = (__bridge_retained void *)obj;
    }
    // 出作用域后,obj强引用消失
    // 由于__bridge_retained,p同时也是强引用,对象得以继续生存
    NSLog("%@", [(__bridge id)p class]);
    
    • __bridge_transfer:

    意为“转换后释放”,原创建方在转换后自动释放自身引用,只由接收方进行内存管理(转换了所有权),与release效果类似:

    void *p = xxx;
    id obj = (__bridge_transfer id)p;
    // 转换后相当于p进行了release操作,只有obj持有对象
    

    OC(Foundation)对象与CF(Core Foundation)对象间的转换

    • 由于二者基本是等效框架(只是实现语言不同),对象间的转换无需消耗CPU资源,是“免费桥接”(“toll-free bridge”)。
    • 一般转换规则:
      • OC -> CF,使用“__bridge_retained”或“CFBridgingRetain”
      • CF -> OC,使用“__bridge_transfer”或“CFBridgingRelease”(因为一般转换为OC对象后,ARC可以自动介入,防止忘记使用CFRelease手动释放内存)

    总结:尽量不要直接使用__bridge进行转换,使用时需再三考虑内存管理情况。


    1. 使用__strong、__weak和__autoreleasing修饰的变量,其初始值会自动赋值为nil

    相关文章

      网友评论

          本文标题:《Objective-C高级编程 iOS与OS X多线程与内存管

          本文链接:https://www.haomeiwen.com/subject/mwmsrqtx.html