浅解ARC中的 __bridge、__bridge_retained和__bridge_transfer

文章来源:http://www.outflush.com/2015/03/introduction-of-arc-bridge-type-transfer/

在对 bridge 相关的修饰符解说前。首先了解下面内容

  • Core Foundation 是一组C语言接口。它与Foundation为相同功能提供接口。仅仅是Foundation框架提供的是Objective-C接口。
  • Core Foundation中的对象也存在引用计数的概念,相似于Foundation的retain/release,其相应的接口是CFRetain/CFRelease
  • 这两个框架的对象之间能够相互转换,这样的转换被称之为Toll-Free bridge
  • 当使用ARC时,Core Foundation中的对象不被ARC所管理。所以Core Foundation和Foundation中的对象在相互转换的过程中会涉及到对象全部权的转换。这里便用到了bridge修饰符。

普通对象与C语言指针之间的转换

void *p = NULL;
{
id obj = [[NSObject alloc] init];
p = (__bridge void *)obj;
}
NSLog(@"Hello");

// 这里会出现错误
NSLog(@"%@", [(__bridge id)p class]);

上面代码中的obj被ARC管理,p是一个C语言指针。不在ARC的管理范围中。当程序运行到obj的作用域之外。ARC便将obj给release掉,这时p指针成为NULL。所以在使用__bridge的时候必须清楚对象的生命周期否则便会出现相似上面的错误。

这时便应该使用__bridge_retain关键字来进行转换

p = (__bridge_retain void *)obj;

// 上面这段代码在非ARC的环境下能够表示为
p = obj;
[(id)p retain];

所以当obj被ARC release后,p指针仍然指向一个有效的对象。

__bridge_transfer则是用于将一个通过__bridge_retain转换得到的C语言指针又一次转换为被ARC管理的普通对象。

id obj = (__bridge_transfer id)p;

// 用非ARC来表示就是
id obj = p;
[obj retain];
[(id)p release];

能够看出,__bridge_transfer将p指向的对象的全部权转移到了ARC管理的obj上。

当在ARC环境中声明 id obj 时。默认是 strong 修饰符修饰的,所以ARC会自己主动对obj进行retain处理。所以说__bridge_transfer仅仅做了release处理。

Core Foundation与Foundation普通对象之间的转换

从上面已经知道Core Foundation中的对象也存在引用计数的概念。当在非ARC环境下,Core Foundation对象和Foundation对象能够通过标准的C语言类型转换来进行转换(Toll-Free bridge)。而当引入ARC后则须要bridge来进行转换,由于你须要明白的告诉编译器怎样处理对象的全部权。

比如:

NSString *str = [NSString stringWithFormat…];
CFStringRef cfStr = (__bridge CFStringRef)str;
...
CFRelease(cfStr);

这里str对象被ARC所管理,而cfStr并不在ARC的管理中,由于__bridge仅仅是单纯的进行了类型转换,所以当str被ARC release后,cfStr便成为了NULL。

而当上面这段代码使用__bridge_retain进行转换后。cfStr便拥有了str对象的全部权,这时假设str被ARC release,cfStr仍然有效。

然而又由于Core Foundation中的对象也存在引用计数概念。所以须要使用CFRelease()手动的对cfStr进行release操作。

代码例如以下:

NSString *str = [NSString stringWithFormat…];
CFStringRef cfStr = (__bridge_retain CFStringRef)str;
...
CFRelease(cfStr);

至于__bridge_transfer,从上文能够得知其用于将对象的全部权转移,所以CF(Core Foundation简写)对象在使用__bridge_transfer转换为Foundation对象后被释放。

CFStringRef cfStr = CFStringCreate…();
NSString *str = (__bridge_transfer NSString *)cfStr;

// 在非ARC环境下,上面这句等同于
NSString *str = cfStr;
CFRelease(cfStr);

实际上,在Core Foundation内部存在两个用于CF对象和Foundation对象转换的函数

CFTypeRef CFBridgingRetain(id X) {
return (__bridge_retained CFTypeRef)X;
}
id CFBridgingRelease(CFTypeRef X) {
return (__bridge_transfer id)X;
}

使用这两个函数相同能够进行两者对象之间的类型转换。

总结

  • bridge 用于被ARC管理的对象和不被ARC管理的对象之间的转换
  • __bridge 仅仅负责单纯的类型转换,须要格外注意对象的生存周期。

  • __bridge_retain 将被ARC管理的对象转换为不被ARC管理的对象的同一时候,将ARC管理的对象retain。使其部分成为不被ARC管理的对象(描写叙述非常不当,自行多揣摩)。
  • __bridge_transfer 将不被ARC管理的对象转换为被ARC管理的对象的同一时候,将不被ARC管理的对象release。

时间: 2024-10-13 03:25:26

浅解ARC中的 __bridge、__bridge_retained和__bridge_transfer的相关文章

[Objective-C]__bridge,__bridge_retained和__bridge_transfer的意思,区别与使用

使用ARC能帮我们减轻不少内存管理方面的负担,尤其是对用惯了Java的程序员来说.但是像我这种Java基础本身就不牢固,做了两年的iOS已经习惯手动管理内存的半吊子,使用ARC还是经常碰壁. 最近碰到了CFObject和NSObject转换的问题,由于ARC不能管理Core Foundation Object的生命周期,所以在Core Foundation和ARC之间,我们需要使用到__bridge,__bridge_retained和__bridge_transfer三个转换关键字. 根据苹果

__bridge,__bridge_retained和__bridge_transfer的意思,区别与使用

最近碰到了CFObject和NSObject转换的问题,由于ARC不能管理Core Foundation Object的生命周期,所以在Core Foundation和ARC之间,我们需要使用到__bridge,__bridge_retained和__bridge_transfer三个转换关键字. 根据苹果官方的文档(https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Int

iOS 开发之__bridge __bridge_retained 和 __bridge_transfer的区别

简介:__bridge:实现id类型与void*类型的相互转换: __bridge_retained:类型被转换时,其对象的所有权也将被变换后变量所持有 __bridge_transfer:类型被转换时,其对象的所有权也将被释放 __bridge_retained 是编译器替我们做了 retain 操作,而 __bridge_transfer 是替我们做了 release1. 详情: 在iOS世界,主要有两种对象:Objective-C 对象和 Core Foundation 对象0.Core

__bridge,__bridge_retained,__bridge_transfer

最近再看CoreText其中有很多地方需使用了__bridge或者CFBridgingRelease 作为菜鸟不太理解什么意思于是百度了下大体回答是这样的 CFObject和NSObject转换的问题,由于ARC不能管理Core Foundation Object的生命周期,所以在Core Foundation和ARC之间,我们需要使用到__bridge,__bridge_retained和__bridge_transfer三个转换关键字. __bridge只做类型转换,但是不修改对象(内存)管

ARC中__bridge, __bridge__transfer, __bridge_retained 关系

现在已经凌晨了,但是我却没发觉困. 琢磨了好久的东西,终于顿悟. 这篇是其中的一个点,记录下来,以备后续查阅! 说到__bridge,就不得不说Objective-C和Core Foundation对象之间的关系. 当你在 Objective-C 和 Core Foundation 对象之间进行转换时,就需要使用 Bridge cast. 今天的多数应用很少需要使用 Core Foundation,大多数工作都可以直接使 用 Objective-C 类来完成.但是某些底层 API,如 Core

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ 浅谈 Linux

浅谈Linux中的信号机制(二)

首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Linux内核源码评头论足.以后的路还很长,我还是一步一个脚印的慢慢走着吧,Linux内核这座山,我才刚刚抵达山脚下. 好了,言归正传,我接着昨天写下去.如有错误还请各位看官指正,先此谢过. 上篇末尾,我们看到了这样的现象:send进程总共发送了500次SIGINT信号给rcv进程,但是实际过程中rcv只接受/处理了1

byte和int的浅解

1.byte范围为什么是(-128~127)? --byte是8位 --这里定义2种8位展现形式:1,符号形式(第一眼看符号位,判断正负,然后计算剩下7位的数值).2,存储形式(内存中都是补码存储) --想要知道一个数在内存中如何存储?真值 >> 符号形式 >> 补码 >> 存储形式 --示例1: +8(真值) +8(符号形式):0000 1000,//真值"+8",因为是"+",所以将第一位定义为0,因为值是"8&qu

浅谈hadoop中mapreduce的文件分发

最近在做数据分析的时候,需要在mapreduce中调用c语言写的接口,此时就需要把动态链接库so文件分发到hadoop的各个节点上,原来想自己来做这个分发,大概过程就是把so文件放在hdfs上面,然后做mapreduce的时候把so文件从hdfs下载到本地,但查询资料后发现hadoop有相应的组件来帮助我们完成这个操作,这个组件就是DistributedCache,分布式缓存,运用这个东西可以做到第三方文件的分发和缓存功能,下面详解: 如果我们需要在map之间共享一些数据,如果信息量不大,我们可