Toll-Free Bridged类型

117 篇文章 0 订阅
73 篇文章 1 订阅

感觉这篇文章不错,转给大家

某些数据类型能够在Core Foundation和Foundation之间互换使用,可被互换使用的数据类型被称为Toll-Free Bridged类型。这意味着同一数据类型即可以作为Core Foundation函数的参数,也可作为接收者向其发送Objective-C消息。Core Foundation与Foundation之间交换使用数据类型的技术被称为Toll-Free Bridging 。

比如,NSString与CFStringRef即一对可以相互转换的数据类型:

CFStringRef

 

但不是所有的数据类型都可以Toll-Free Bridging,比如说NSRunLoop与CFRunLoop,NSBundle与CFBundle,NSDateFormatter与CFDateFormatter都不可以相互转换。

编译器不能够自动管理Core Foundation对象的声明周期。MRC下的Toll-Free Bridging因为不涉及内存管理的转移,可以直接相互bridge而不必使用类似__bridge修饰字。而在ARC下,由于ARC能够管理Objective-C对象的内存,却不能管理CF对象,CF对象依然需要我们手动管理内存。

Toll-Free Bridging实现原理

每一个能够bridge的ObjC类,都是一个类簇(class cluster)。类簇是一个公开的抽象类,但其核心功能的是在不同的私有子类中实现的,公开类只暴露一致的接口和实现一些辅助的创建方法。而与该ObjC类相对应的Core Foundation类的内存结构,正好与类簇的其中一个私有子类相同。

举个例子,NSString是一个类簇,一个公开的抽象类,但每次创建一个NSString的实例时,实际上我们会获得其中一个私有子类的实例。而NSString的其中一个私有子类实现既为NSCFString,其内存的结构与CFString是相同的,CFString的isa指针就指向NSCFString类,即CFString对象就是一个NSCFString类的实例。
所以,当NSString的实现刚好是NSCFString的时候,他们两者之间的转换是相当容易而直接的,他们就是同一个类的实例。

当NSString的实现不是NSCFString的时候(比如我们自己subclass了NSString),我们调用CF函数,就需要先检查对象的具体实现。如果发现其不是NSCFString,我们不会调用CF函数的实现来获得结果,而是通过给对象发送与函数功能相对应的ObjC消息(调用相对应的NSString的接口)来获得其结果。

例如CFStringGetLength函数,当收到一个作为参数传递进来的对象时,会先确认该对象到底是不是NSCFString实现。如果是的话,就会直接调用CFStringGetLength函数的实现来获得字符串的长度;如果不是的话,会给对象发送length消息(调用NSString的length接口),来得到字符串的长度。

 ARC下的Toll-Free Bridging 

由于MRC下的Toll-Free Bridging因为不涉及内存管理的转移,相互之间可以直接交换使用

MRCBridging

 

但在ARC中,在CF和ObjC之间bridge对象的时候,编译器就不知道该如何处理这个同时有ObjC指针和CFTypeRef指向的对象。你必须为编译器提供额外的信息:将类型显示转换为互换类型;同时可能需明确对象的声明周期。 因此我们需要使用__bridge, __bridge_retained, __bridge_transfer修饰符告诉编译器该如何去做。

__bridge 

最常用的修饰符,这意味着编译器不做任何内存管理的事情,编译器仍然负责管理好在Objc一端的引用计数的事情,开发者也继续负责管理好在CF 一端的事情(至于开发者如何处理就^_~)。

bridging1

 

编译器会继续负责nsStr的内存管理的事情,不会在bridge的时候retain对象,所以也不需要开发者在CF 一端释放。需要注意的是,当nsStr被释放的时候(比如出了作用域),意味着cfStr指向的对象被释放了,这时如果继续使用cfStr将会引起程序崩溃。

bridging2

 

bridge的时候编译器不会做任何内存管理的事情,bridge之后,编译器会负责ObjC一端的内存管理的事情。同时,开发者需要负责管理CF 一端的内存管理的事情,需要在bridge之后,负责release对象。

__bridge_retained(或CFBridgingRetain) 

接着上面的例子,Foundation类型对应的Core Foundation类型时,为了防止nsStr被释放,引起我们使用cfStr的时候程序崩溃,可以使用__bridge_retained修饰符。这意味着,在bridge的时候,编译器会retain对象,而由开发者在CF一端负责release。这样,就算nsStr在objc一端被释放,只要开发者不手动去释放cfStr,其指向的对象就不会被真的销毁。但同时,开发者也必须保证和负责对象的释放。

bridging3

 

__bridge_transfer(或CFBridgingRelease) 

当Core Foundation类型转化为Foundation类型时,如果使用__bridge修饰符在cf转objc的时候非常的麻烦,我们既需要一个CFTypeRef的变量,还需要在bridge之后负责释放。这时我们可以使用__bridge_transfer,意味着在bridge的时候,编译器转移了对象的所有权,开发者不再需要负责对象的释放。

bridging4

 

总结

  • (__bridge T) op:编译器在bridge的时候不要做任何事情
  • (__bridge_retained T) op:(ObjC转CF的时候使用)编译器在bridge的时候retain对象,开发者需要在CF一端负责释放对象
  • (__bridge_transfer T) op:(CF转ObjC的时候使用)编译器转移CF对象的所有权,开发者不再需要在CF一端负责释放对象
转:http://edsioon.me/toll-free-bridged%E7%B1%BB%E5%9E%8B/
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值