美文网首页
Core Foundation对象的内存管理

Core Foundation对象的内存管理

作者: _Joeyoung_ | 来源:发表于2018-03-09 18:23 被阅读87次

    Core Foundation 对象主要使用在C语言编写的 Core Foundation 框架中,并使用引用计数的对象。在 MRC(Manaual Reference Counting)中,Core Foundation 框架中的 retain/release 分别是 CFRetain/CFRelease。
    Core Foundation 对象与 Objective-C 对象的区别很小,不同之处只是在于是由哪一个框架(Foundation 框架还是 Core Foundation 框架)所生成的。无论哪个框架生成,都可以交替使用。Foundation 框架的API生成并持有的对象可以用 Core Foundation 框架的API释放,反之亦然。
    因为 Core Foundation 对象与 Objective-C 对象没有区别,所以在 MRC 时,只用简单的C语言的转换也能实现互换。这种转换不需要使用额外的CPU资源,因此也被成为“免费桥”(Toll-Free Bridge)。

    __bridge:只做类型转换,不修改相关对象的引用计数。

    例:

    CFMutableArrayRef cfArray = NULL;
    {
        /*
         * 变量 obj 生成并持有对象的强引用
         */
        NSMutableArray *obj = [[NSMutableArray alloc] init];
    
        /*
         * 因为 __bridge 转换不改变对象的持有状态,cfArray 不持有对象的强引用
         */
        cfArray = (__bridge CFMutableArrayRef)obj;
        printf("retain count = %ld\n",CFGetRetainCount(cfArray));
    }
    
    /*
     * 因为 变量obj 超出作用域,对象得到释放
     * 再次访问对象出错!(悬垂指针)
     */
    printf("retain count after the scope = %ld\n",CFGetRetainCount(cfArray));
    
    控制台:

    __bridge_retained(等价于 CFBridgingRetain):类型转换后,将相关对象的引用计数加1。

    例:

    CFMutableArrayRef cfArray = NULL;
    {
        /*
         * 变量 obj 生成并持有对象的强引用
         */
        NSMutableArray *obj = [[NSMutableArray alloc] init];
        
        /*
         * 通过 __bridge_retained 将对象CFRetain赋值给 cfArray,引用计数+1
         */
        cfArray = (__bridge_retained CFMutableArrayRef)obj;
        // cfArray = CFBridgingRetain(obj); 作用同上
        printf("retain count = %ld\n",CFGetRetainCount(cfArray));
    
    }
    
    /*
     * 因为 变量obj 超出作用域,对其强引用失效,引用计数-1
     */
    printf("retain count after the scope = %ld\n",CFGetRetainCount(cfArray));
    
    /*
     * 不再使用对象时,将其释放掉
     */
    CFRelease(cfArray);
    
    控制台:

    __bridge_transfer(等价于 CFBridgingRelease):类型转换后,将该对象的引用计数交给ARC管理,Core Foundation 对象在不用时,不需要调用 CFRelease 方法。

    例:

    NSMutableArray *obj = NULL;
    {
        /*
         * 变量 cfArray 生成并持有对象的强引用,引用计数为“1”
         */
        CFMutableArrayRef cfArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
        
        printf("retain count = %ld\n",CFGetRetainCount(cfArray));
        
        /*
         * 通过 __bridge_transfer 赋值,
         * 变量 obj 持有对象强引用,cfArray不再持有对象的强引用,引用计数不变,为“1”
         */
        obj = (__bridge_transfer NSMutableArray *)cfArray;
        // obj = CFBridgingRelease(cfArray); 作用同上
    
        /*
         * 经由 __bridge_transfer 转换后,
         * 赋值给变量 cfArray 中的指针也指向仍然存在的对象(只是不再持有对象的强引用),所以可以正常使用
         */
        printf("retain count after the cast= %ld\n",CFGetRetainCount(cfArray));
    }
    
    /*
     * 因为 变量obj 持有对象的强引用,
     * 即使超出 变量cfArray 的作用域,仍然可以正常使用
     */
    NSLog(@"class = %p",obj);
    
    控制台:

    虽然 Objective-C 和C语言的桥接转换编译器会有智能提示,但是知道其所有权原理对于我们写出高质量的代码还是很有必要的。

    千里之行,始于足下~

    相关文章

      网友评论

          本文标题:Core Foundation对象的内存管理

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