您的位置:首页 > Web前端

__bridge,__bridge_retained和__bridge_transfer三个转换关键字 - iOS开发

2014-03-21 14:20 323 查看
4000

最近碰到了CFObject和NSObject转换的问题,正因为Objective-C是ARC管理的对象,而Core Foundation不是ARC管理的对象,即:ARC不能管理Core Foundation Object的生命周期,所以在Core Foundation和ARC之间,我们需要使用到__bridge,__bridge_retained和__bridge_transfer三个转换关键字。

根据苹果官方的文档(https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html):

__bridge只做类型转换,但是不修改对象(内存)管理权;

__bridge_retained(也可以使用CFBridgingRetain)将Objective-C的对象转换为Core Foundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;

__bridge_transfer(也可以使用CFBridgingRelease)将Core Foundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。

CoreFoundation里面的CFStringRef和NSString*是可以直接转换的,两种也都有一个相似的用来直接赋常量的操

作。例如:

CFStringRef a = CFSTR("a");

NSString *b = @"b";

CFSTR是一个宏,这个宏的定义可能是CFStringMakeConstantString,也可能是__builtin___CFStringMakeCo-

nstantString。如果是CFStringMakeConstantString,看看CFStringMakeConstantString的实现就会明白,

CFSTR("a")是存放在一个全局字典里面的,下次用到CFSTR("a")的时候先查字典里面有没有,如果有就是用存

在的,如果没有则分配一个,并且放到字典里面。

所以这里有两个需要注意的,一:CFSTR分配出来的字符串对象是不能自己释放的,如果你释放了下次在使用就

会使用到一个野对象;二:多线程使用可能会出问题,因为全局的字典是没有锁的。

一下是结合代码解释:

__bridge

NSString *string = [NSString stringWithFormat:...];

CFStringRef cfString = (__bridge CFStringRef)string;

只是单纯地执行了类型转换,没有进行所有权的转移,也就是说,当string对象被释放的时候,cfString也不能被使用了。

__bridge_retained
NSString *string = [NSString stringWithFormat:...];
CFStringRef cfString = (__bridge_retained CFStringRef)string;
CFRelease(cfString); // 由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己调用CFRelease(cfString)来release对象
使用 __bridge_retained 可以通过转换目标处(cfString)的 retain 处理,来使所有权转移。即使 string 变量被释放,cfString 还是可以使用具体的对象。只是有一点,由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己调用CFRelease(cfString)来release对象。

__bridge_transfer
所有权被转移的同时,被转换变量将失去对象的所有权。当Core Foundation对象类型向Objective-C对象类型转换的时候,会经常用到 __bridge_transfer 关键字。
CFStringRef cfString = CFStringCreate...();
NSString *string = (__bridge_transfer NSString *)cfString;
// CFRelease(cfString); 因为已经用 __bridge_transfer 转移了对象的所有权,所以不需要调用 release

实际上,Core Foundation 内部,为了实现Core Foundation对象类型与Objective-C对象类型的相互转换,提供了下面的函数。

CFTypeRef CFBridgingRetain(id X) {

return (__bridge_retained CFTypeRef)X;

}

id CFBridgingRelease(CFTypeRef X) {

return (__bridge_transfer id)X;

}

所以,可以用 CFBridgingRetain 替代 __bridge_retained 关键字:

NSString *string = [NSString stringWithFormat:...];

CFStringRef cfString = CFBridgingRetain(string);

CFRelease(cfString); // 由于Core Foundation不在ARC管理范围内,所以需要自己调用CFRelease(cfString)来release对象。

同样,我们可以使用 CFBridgingRelease() 来代替 __bridge_transfer 关键字。

CFStringRef cfString = CFStringCreate...();

NSString *string = CFBridgingRelease(cfString);

高级iOS开发技术交流群:415239068,欢迎大家加入
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: