总结于 IOS Tuturial 中 ARC两章,详细在dropbox pdf 文档。

Toll-Free Bridging

当你在 Objective-C 和 Core Foundation 对象之间进行转换时,就需要使用 Bridge cast。

今天的多数应用很少需要使用 Core Foundation,大多数工作都可以直接使 用 Objective-C 类来完成。但是某些底层 API,如 Core Graphics 和 Core Text, 都基于 Core Foundation,而且不太可能会有 Objective-C 的版本。幸运的是, iOS 的设计使得这两种类型的对象非常容易转换。

例如 NSString 和 CFStringRef 就可以同等对待,在任何地方都可以互换使 用,背后的设计就是 toll-free bridging。在 ARC 之前,只需要使用一个简单 的强制类型转换即可:

当然,alloc 分配了 NSString 对象,你需要在使用完之后进行释放,注意是 释放转换后的 CFStringRef 对象:
CFRelease(s1);

反过来,从 Core Foundation 到 Objective-C 的方向也类似:

现在我们使用了 ARC,情况变得不一样!以下代码在手动内存管理中是完全 合法的,但在 ARC 中却存在问题:
- (NSString *)escape:(NSString *)text
{

CFStringRef s1 = (CFStringRef) [[NSString alloc]

initWithFormat:@"Hello, %@!", name];

CFStringRef s2 = CFStringCreateWithCString(kCFAllocatorDefault, bytes,

kCFStringEncodingMacRoman);

NSString *s3 = (NSString *)s2;

// release the object when you're done

[s3 release];

return [(NSString *)CFURLCreateStringByAddingPercentEscapes(

NULL,

(CFStringRef)text,

NULL,

(CFStringRef)@"!*'();:@&=+$,/?%#[]", // 这里不需要 bridging

casts,因为这是一个常量,不需要释放!

CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncodin

g))

autorelease];

}

首先需要移除 autorelease 调用。然后编译器还会报两个类型转换错误:

 Cast of C pointer type 'CFStringRef' to Objective-C pointer type 'NSString *' requires a bridged cast

 Cast of Objective-C pointer type 'NSString *' to C pointer type 'CFStringRef' requires a bridged cast

错误分别来自以下两行代码:

编译器必须知道由谁来负责释放转换后的对象,如果你把一个 NSObject 当 作 Core Foundation 对象来使用,则 ARC 将不再负责释放该对象。但你必须明确 地告诉 ARC 你的这个意图,编译器没办法自己做主。同样如果你创建一个 Core Foundation 对象并把它转换为 NSObject 对象,你也必须告诉 ARC占据对象的所 有权,并在适当的时候释放该对象。这就是所谓的 bridging casts。

CFURLCreateStringByAddingPercentEscapes()函数的参数需要两个 CFStringRef 对象,其中常量NSString 可以直接转换,因为不需要进行对象释 放;但是 text 参数不一样,它是传递进来的一个NSString 对象。而函数参数 和局部变量一样,都是 strong 指针,这种对象在函数入口处会被 retain,并且 对象会持续存在直到指针被销毁(这里也就是函数返回时)。

对于 text 参数,我们希望 ARC 保持这个变量的所有权,同时又希望临时将 它当作 CFStringRef 对象来使用。这种情况下可以使用__bridge 说明符,它告 诉 ARC 不要更改对象的所有权,按普通规则释放该对象即可。

多数情况下,Objective-C 对象和 Core Foundation 对象之间互相转换时, 我们都应该使用__bridge。但是有时候我们确实需要给予 ARC 某个对象的所有权, 或者解除 ARC 对某个对象的所有权。这种情况下我们就需要使用另外两种 bridging casts:

  • __bridge_transfer:给予 ARC 所有权

  • __bridge_retained:解除 ARC 所有权

    在上面代码中,"return (NSString *)CFURLCreateStringByAddingPercentEscapes",编译器弹出的修复提示有两个:

    两个解决办法:__bridge 和 __bridge_transfer,正确的选择应该 是 __bridge_transfer。

    因为 CFURLCreateStringByAddingPercentEscapes() 函数创建了一个新 的 CFStringRef 对象,当然我们要的是 NSString 对象,因此我们使用了强制转 换。实际上我们真正想要做的是:

    从 CFURLCreateStringByAddingPercentEscapes 函数的 create 可以看 出,函数会返回一个 retain 过的对象。某个人需要负责在适当的时候释放该对 象,如果我们不把这个对象返回为 NSString,则通常我们需要自己调用:

    {

    }

    不过 ARC 只能作用于 Objective-C 对象,不能释放 Core Foundation 对象。 因此这里你仍然需要调用 CFRelease()来释放该对象。

    这里我们的真实意图是:转换新创建的 CFStringRef 对象为 NSString 对象, 并且当我们不再需要使用这个 NSString 对象时,ARC 能够适当地释放它。

    因此我们使用 __bridge_transfer告诉ARC:"嘿!ARC,这个CFStringRef 对象现在是一个 NSString对象了,我希望你来销毁它,我这里就不调用 CFRelease()来释放它了"。

    如果我们使用 __bridge,就会导致内存泄漏。ARC并不知道自己应该在使 用完对象之后释放该对象,也没有人调用 CFRelease()。结果这个对象就会永远 保留在内存中。因此选择正确的bridge 说明符是至关重要的。

    为了代码更加可读和容易理解,iOS 还提供了一个辅助函数: CFBridgingRelease()。函数所做事情和 __bridge_transfer 强制转换完全一 样,但更加简洁和清晰。CFBridgingRelease() 函数定义为内联函数,因此不会 导致额外的开销。函数之所以命名为 CFBridgingRelease(),是因为一般你会在需要使用 CFRelease()释放对象的地方,调用 CFBridgingRelease()来传递对象 的所有权。

    因此最后我们的代码如下:

    - (NSString *)escape:(NSString *)text

    {

    }

    另一个常见的需要 CFBridgingRelease 的情况是 AddressBook framework:

    - (NSString *)firstName

    {

    }

    只要你调用命名为 Create, Copy, Retain 的 Core Foundation 函数,你都 需要使用CFBridgingRelease()安全地将值传递给ARC。

    __bridge_retained 则正好相反,假设你有一个 NSString 对象,并且要将 它传递给某个 Core Foundation API,该函数希望接收这个 string 对象的所有 权。这时候你就不希望 ARC 也去释放该对象,否则就会对同一对象释放两次,而 且必将导致应用崩溃!换句话说,使用 __bridge_retained 将对象的所有权给 予 Core Foundation,而 ARC 不再负责释放该对象。

    如下面例子所示:

    return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(

    NULL,

    (__bridge CFStringRef)text,

    NULL,

    CFSTR("!*'();:@&=+$,/?%#[]"),

    CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncodin

    g)));

    return CFBridgingRelease(ABRecordCopyCompositeName(...));

    NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];

    CFStringRef s2 = (__bridge_retained CFStringRef)s1;

    // do something with s2

    // . . .

    CFRelease(s2);

一旦 (__bridge_retained CFStringRef) 转换完成,ARC 就不再负责释放该 对象。如果你在这里使用__bridge,应用就很可能会崩溃。ARC 可能在 Core Foundation 正在使用该对象时,释放掉它。

同样__bridge_retained 也有一个辅助函数:CFBridgingRetain()。从名字 就可以看出,这个函数会让Core Foundation 执行 retain,实际如下:

现在你应该明白了,上面例子的 CFRelease()是和 CFBridgingRetain()对应 的。你应该很少需要使用__bridge_retained 或 CFBridgingRetain()。

__bridge 转换不仅仅局限于 Core Foundation 对象,某些 API 使用 void * 指针作为参数,允许你传递任何东西的引用:Objective-C 对象、Core Foundation 对象、malloc()内存缓冲区等等。void *表示这是一个指针,但实际的数据类型 可以是任何东西!

要将 Objective-C 对象和 void *互相转换,你也需要使用__bridge 转换, 如下:

在 animation delegate 方法中,你再将对象强制转回来:

{

}

总结:

  • 使用 CFBridgingRelease(),从 Core Foundation 传递所有权给 Objective-C;

  • 使用 CFBridgingRetain(),从 Objective-C 传递所有权给 Core Foundation;

  • 使用__brideg,表示临时使用某种类型,不改变对象的所有权。

IOS学习 ARC下__bridge相关推荐

  1. IOS之Objective-C学习 ARC下的单例模式

    单例模式是我常用的一种设计模式,最常见的用途就是用来保存数据并且传递数据.这都归功于单例模式的特性,首先就让我为大家简单介绍一下单例模式的特性. 单例模式的三大特性: 1.某个类只能有一个实例: 2. ...

  2. IOS学习——ARC初识

    本文转载自吴茜的转载,由于原文链接失效,出处写为该美女的链接:http://blog.csdn.net/yiyaaixuexi/article/details/7351104 ARC是什么 ARC是i ...

  3. [iOS]ARC下循环引用的问题

    转载自:http://blog.cnbang.net/tech/2085/ [iOS]ARC下循环引用的问题 2013-8-30 最初 最近在开发应用时碰到使用ASIHttpRequest后在某些机器 ...

  4. ios 内存管理的理解(三)ARC下 对象内存管理

    1 ARC工作原理详述 ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只不过是在代码编译时为你自动在合适的位置插入release或autorelease 2 ...

  5. linux下json数据解析,JSON数据解析 - iOS学习笔记_Linux编程_Linux公社-Linux系统门户网站...

    在之前的<iOS学习--xml数据解析(九)>http://www.linuxidc.com/Linux/2014-02/97020p9.htm 介绍了xml数据解析,这一篇简单介绍一下J ...

  6. iOS开发ARC内存管理技术要点

    本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇 ...

  7. iOS开发ARC入门和使用

    本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流和讨论.请不要将本文的部分或全部内容用于商用,谢谢合作. 欢迎转载本文,但是转载请注明本文出处:http:/ ...

  8. iOS开发ARC内存管理

    本文的主要内容: ARC的本质 ARC的开启与关闭 ARC的修饰符 ARC与Block ARC与Toll-Free Bridging ARC的本质 ARC是编译器(时)特性,而不是运行时特性,更不是垃 ...

  9. block的理解 ios_深入理解iOS的block (下)

    对象类型的auto变量 例子一 首先看一个简单的例子 定义一个类 YZPerson,里面只有一个dealloc方法 @interface YZPerson : NSObject @property ( ...

最新文章

  1. 手把手带你复现AI+区块链写码全过程!(附代码视频)
  2. c语言结构体如何定义字母,c语言中定义结构体如何定义?
  3. 使用Rekit开发可扩展的前端应用
  4. opencv机器学习线性回归_机器学习入门1---简单线性回归
  5. BUGLY集成升级空指针问题
  6. epoll非阻塞IO
  7. 【剑指offer - C++/Java】13、调整数组顺序使奇数位于偶数前面
  8. 牛客13592 武藏牌牛奶促销
  9. VMware创建Linux及局域网内独立访问IP和访问外网IP的配置
  10. 【技巧】搜狗输入法特殊技巧
  11. 微信读书App来了 小伙伴们快去占榜吧
  12. 台式计算机键盘驱动,提示检测到不兼容的键盘驱动程序怎么解决 教你几个步骤轻松修复...
  13. uni-app:mescroll-uni 实现上拉加载,下拉刷新
  14. python读取写入pickle、npy格式文件(代码+注释)
  15. StyleGAN生成模型
  16. Arduino应用开发——通过小爱同学控制灯光
  17. 本科计算机 在职研究生想读英语,想读在职研究生但是英语成绩不好怎么办?...
  18. C++友元和友元函数
  19. SAP—IDoc操作步骤
  20. 国产操作系统调研 -- 银河麒麟4.0.2

热门文章

  1. 麻省理工算法导论(含教材、讲义、答案)
  2. 计算机与数学文化论文参考文献,数字电子技术参考文献
  3. itext7生成pdf教程
  4. 【GDOI模拟】飞机调度
  5. 微信图片禁止外链 此图片来自微信公众平台未经允许不可引用
  6. 【云豹直播系统】专业制作仿映客手机直播app、视频直播系统
  7. 产品经理笔试:其他答题注意事项
  8. ROS:坐标管理系统
  9. 深刻理解电源完整性PI,图文并茂,浅显易懂
  10. 单片机又称单片微计算机,最初的英文缩写是SCM