美文网首页
对象的免费桥接

对象的免费桥接

作者: 青春未过 | 来源:发表于2018-02-04 21:43 被阅读4次

Core Foundation

Core Foundation 杠框架使用一个朴素的C语言编写的纯手工创建的对象系统。CF对象具有它们自己的音独的引用计数系统。从其名称中具有的单词"Create"、"Copy"的函数获得的对象在返回时将具有“+1的保留计数”。CFRetain(aCFObject)函数将把aCFObject的保留计数加1,而CFRelease(aCFObject)函数则会把aCFObject的保留计数减1。 当一个对象的保留计数归零时,它将被取消分配。如果你从一个“Create”、“Copy”函数接收到对象,最终必须通过调用CFRelease来抵消创建或复制。如果不这样做,就会产生内存泄漏。

ARC不会使用这个单独的引用计数系统自动化。 如果你在使用CF对象,就要负责理解手动引用计数,并且正确地保留和释放你的CF对象

ARC 与 Core Foundation 之间的免费桥接

从免费桥接的一方到别一方的强制转换对于ARC而言都是一个问题。当把一个对象从CF强制转成OC(或者采用相反方向)时,结果将得到单个对象,它的保留计数可以被两个不同的不会彼此交流的系统操纵。ARC对CF的内存管理约定一无所知,使事情更坏的是,你可以直接控制其中一个系统(CF),但不能控制另一个系统ARC。就像由两位厨师一起做一碗汤一样,会引起烹饪麻烦。
编译器避免这种麻烦的方式是禁止在OC对与CF对象之间进行强制转换。解决这个问题的方式是:通过一种称为 桥接强制转换(brige casts) 的特殊的强制转换类型给ARC提供一些额外的信息 有以下三种情况

  • 强制转换不转移所有权
  • 强制转换把所有权转出CF并转入ARC中
  • 强制转换把所有权转出ARC 并转入CF中

强制转换不会转移所有权

在这种情况下,一方只会从另一方临时“借用”对象,而不会转移所有权
__bridge告诉ARC在强制转换下不会转移所有权。

    // CF---->OC
    CFStringRef cfstr =  CFStringCreateWithCString(NULL, "hello cfstring!", kCFStringEncodingUTF8);
    NSString * ocstr = (__bridge NSString*)cfstr;
    //只是类型的转换,没有进行所有权的交接
    NSLog(@"%@",ocstr);
    CFRelease(cfstr);
    // 内存管理仍需要所手动释放

    //OC --> CF
    NSString * ocString = @"hello objective C string!";
    CFStringRef cfstring = (__bridge CFStringRef)ocString;
    // 只是类型转换,对象释放仍由ARC来进行管理,不需要进行手动释放该cfstring
 // 生成gif文件路径
    NSString * gifpath = [imgDir stringByAppendingPathComponent:@"newgif.gif"];
    CFURLRef  urlref = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)gifpath, kCFURLPOSIXPathStyle, NO);
    CFRelease(urlref);
    NSString * gifpath = [imgDir stringByAppendingPathComponent:@"newgif.gif"];
    CFURLRef  urlref = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFBridgingRetain(gifpath)/**只做类型的转换,不需要移交所有权*/, kCFURLPOSIXPathStyle, NO);//这里会造内存泄漏

强制转换把所有权转出CF并转入ARC中

__bridge_transfer强制转换将把所有权从CF转移给ARC。它告诉ARC在CF一方有一个没有抵消的保留计数,最终必须通过一个release抵消它。ARC负责发送该release消息

    CFStringRef cfstring = CFStringCreateWithCString(NULL, "hello CFStringRef object", kCFStringEncodingUTF8);
    NSString * ocString = (__bridge_transfer NSString*)cfstring;
    // ARC 将接替CF的所有权,负责ocString的释放,其将会在不再使用ocString对象时,向该对象发送一条release消息
    NSLog(@"%@",ocString);

强制转换把所有权转出ARC并转入CF中

__bridge_retain强制转换采用的是相反的方向,它把所有权从ARC中转移给CF。它告诉ARC抵消对象创建的责任传递给了CF。当CF代码用完对象后,它必须利用对象作为参数来调用CFRelease()

    NSString * ocObject = @"我将放器ARC的内存管理,转入CF的内存管理系统";
    CFStringRef cfObject = (__bridge_retained CFStringRef)ocObject;
    // CF接管现OC对象的所有权,它的释放由CF来负责,必须手动进行释放
    CFRelease(cfObject);

利用宏隐藏强制转换

可以利用宏CFBrigingRelease()CFBrigingRetain()分别隐藏__bridge_transfer__bridge_retain强制转换,来改进代码的美感。

    // 以下两行代码将做相同的事情
    NSString * ocString = (__bridge_transfer NSString*)cfstring;
    NSString * ocString = CFBridgingRelease(cfstring);

    // 以下两行代码将做相同的事情
    CFStringRef cfObject = (__bridge_retained CFStringRef)ocObject;
    CFStringRef cfObject = CFBridgingRetain(ocObject);

与void*之间来回进行强制转换

ARC禁止在对象指针与类型化void*的变量之间直接进行强制转换。
其原因与ARC禁目对象指针与CF类型之间直接进行大多数强制转换原因相同。如果把一个对象指针强制转换成void*,将把该对象提供给一个未知量。ARC不会管理非OC指针,因为它无法跟踪一个void*变量中存储的对象所发生的事情,别外,如果把一个void*指针强转为OC对象,ARC将无法确定对象的所有权状态。
如果确信知道自己正在做什么,可以使用桥接来转换支配ARC:

    NSMutableArray * array = [NSMutableArray arrayWithObject:@"hello OC object"];
    //    void * cPointer = (void*)array;//Cast of Objective-C pointer type 'NSMutableArray *' to C pointer type 'void *' requires a bridged cast  这样编译器会不报错
    void * cPointer = (__bridge void*)array;//这样是OK 的

小心: __bridge 强制转没有内存管理的隐含意思,并且void*不是强引用,如果指向对象的所有的强引用都消失了,就会取消分配对象,并且void*变理可能保存一个指向死对象的指针.

ARC 和额外的自动释放池

使用ARC,你将不知道特定的对象是否将被释放或者自动释放,或者它将被取消分配的确切时间,不过当你的代码将创建许多只在短时间内需要的对象时,仍然可以使用额外的自动释放时来限制内存占用:

   for (int i = 0; i<10000; i++) {
        @autoreleasepool{
            // 创建监时的对象
        }
    }

@autoreleasepool的作用域确保:在循环的单独一次迭代中创建的任何临时对象都会在不晚于循环的底部位置收到一个release消息,在那个位置@autoreleasepool的作用域将终结,并会清空对应的自动释放池,ARC可能决定在更早的时间给这样的对象发送一条release消息,而不是自动释放它们,但是额外的@autoreleasepool作用域将会阻止随着循环的每次迭代而使用当前自动释放池中的对象数量增加的情况发生。

相关文章

  • 对象的免费桥接

    Core Foundation Core Foundation 杠框架使用一个朴素的C语言编写的纯手工创建的对象系...

  • Toll-free bridging

    字面意思是“免费桥接技术”,桥接的是Core Foundation框架和 Foundation框架之间的数据。 通...

  • 结构型模式-桥接模式

    开发时,需要增加桥对象,可切换对接对象,实现不同桥功能 桥接模式: 桥接是用于把抽象化与实现化解耦,使得二者可以独...

  • Java设计模式——桥接模式

    Java设计模式之桥接模式 回顾 上一期分享了适配器模式,主要为了实现解耦 桥接模式 简介 桥接模式是对象的结构模...

  • 设计模式(7) 桥接模式

    桥接模式的概念与实现 为什么叫桥接模式 桥接模式的适用场景 继承是面向对象的三大特性之一,但很多时候使用继承的结果...

  • 身为java开发人员,你知道桥接模式还能这样用吗?

    桥接模式 桥接模式定义: 桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,...

  • 设计模式[10]-桥接模式-Bridge Pattern

    1. 桥接模式 桥接模式(Bridge Pattern)是结构性设计模式,可以处理多个维度的对象变化。如果系统中存...

  • C4D 多边形建模

    M系 快捷键功能M系ma创建点mb桥接多个物体之间桥接, 多选对象, 选择connect objects + de...

  • js设计模式-桥接模式

    桥接模式 什么是桥接模式把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化 例子:男生 女...

  • __bridge

    阅读:iOS 学习日志(5) -----ARC中的__bridgeARC下OC对象和CF对象之间的桥接(bridg...

网友评论

      本文标题:对象的免费桥接

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