浅解ARC中的 __bridge、__bridge_retained和__bridge_transfer

浅解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。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116290.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月23日 下午2:00
下一篇 2022年1月23日 下午2:00


相关推荐

  • Jquery确认对话框弹出

    Jquery确认对话框弹出Jquery确认对话框弹出

    2022年4月23日
    94
  • vue双向绑定原理 面试_vue首屏加载优化

    vue双向绑定原理 面试_vue首屏加载优化vue.js采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我…

    2022年10月17日
    7
  • PHP操作MySQL对表增加一列(一个字段)

    PHP操作MySQL对表增加一列(一个字段)

    2021年9月19日
    70
  • Xlsx结合File-Saver实现前端页面表格导出Excel为文件

    Xlsx结合File-Saver实现前端页面表格导出Excel为文件系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:第一章Python机器学习入门之pandas的使用提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例

    2022年6月28日
    33
  • c语言数组介绍

    c语言数组介绍文章目录一、一维数组的创建和初始化1.数组的创建2.数组的初始化3.一维数组的使用4.一维数组在内存中的存储二、二维数组的创建和初始化1.二维数组的创建2.二维数组的创建3.二维数组的创建4.二维数组在内存中的存储二、数组越界1.数组名是什么?一、一维数组的创建和初始化1.数组的创建数组是一组相同类型元素的集合。数组的创建方式:type_tarr_name[const_n];//type_t是指数组的元素类型//const_n是一个常量表达式,用来指定数组的大小数组创建的实

    2022年7月11日
    25
  • Eclipse提示:The import java.util cannot be resolved「建议收藏」

    Eclipse提示:The import java.util cannot be resolved「建议收藏」Eclipse提示:The import java.util cannot be resolved

    2022年4月24日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号