自Xcode4.2开始导入ARC机制后,为了支持对象间的转型,Apple又增加了许多转型用的关键字。
id obj = [[NSObject alloc] init];
void *p = (_bridge void *)obj;
id o = (_bridge id)p;
将objective-C的对象类型用_bridge转换为void*类型和使用_unsafe_unretained关键字修饰的变量是一样的。被代入对象的所有者需要明确对象声明周期的管理,不要出现异常访问的问题。
除过_bridge意外,还有两个_bridge相关的类型转换关键字:
_bridge_transfer
_bridge_retained
区别:_bridge_transfer当想把本来拥有所有权的变量,在类型转换后,让其释放原先所有权的时候,需要使用_bridge_transfer关键字。
如果ARC无效的时候,需要写下面的代码。
id obj = (id)p;
[obj retain];
[(id)p release];
那么ARC有效后,可以用下面的代码来替换
id obj = (_bridge_transfer id)p;
可以看出来,_bridge_retained是编译器替我们做了retain操作,而_bridge_transfer是替我们做了release。
在IOS中,主要由两种对象:objective-C对象和Core Foundation对象。Core Foundation对象主要是有C语言实现的Core Foundation Framework的对象,其中也有对象引用计数的概念,只是不是Cocoa Framework::Foundation Framework的retain/release,而是自身的CFRetain/CFRelease接口。这两种对象间可以互相转换和操作,不适用ARC的时候,单纯的用C类型转换,不需要消耗CPU资源。所以叫做Toll-Free bridged。比如NSArray和CFArrayRef,NSString和CFStringRef,虽然属于不同的Framework,但是具有相同的对象结构,所以可以用标准C的类型转换。
比如不使用ARC时,用下面的代码:
NSString *string = [NSString stringWithFormat:...];
CFStringRef cfString = (CFStringRef)string;
同样,Core Foundation类型向objective-C类型转换时,也是简单地用标准C的类型转换即可。正因为Objective-C是ARC管理的对象,而Core Foundation不是ARC管理的对象,所以才要特意这样转换,这与id类型向void*转换是一个概念。也就是说,当这两种类型(有ARC管理,没有ARC管理)在转换时,需要告诉编译器怎样处理对象的所有权。