Objective-C中的ARC机制不能使用C的结构指针, 而cocoa 为基于C鱼呀你的 Core Foundation框架 和 Foundation 框架数据类型提供了互用性, 这种功能称为直接桥接。
隐式类型转换
CFStringRef cstr = CFStringCreateWithString(NULL, "Hello, World!", KCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:cstr];
由于NSArray中存的是id类型, 而cstr是CFStringRef(直接桥接), 所以这里可以采用隐式类型转换。
显式类型转换
CFStringRef cstr = CFStringCreateWithString(NULL, "Hello, World!", KCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:(NSString *)cstr];
这里采用显式类型转换, 但注意这两种情况均不能在ARC下使用, 因为ARC不能自动处理core Foundation类型。
在使用ARC时,我们可以使用ARC桥接转换
__bridge 可以在不改变所有权的情况下,将对象从Core Foundation转变成 Foundation, 就是说, 如果在ARC的情况下, 有一个Foundation对象,经过我们转换后成了 Core Foundation 但是 它的内存仍然归 ARC管理。 反过来, 当我们先创建了一个 Core Foundation 又把它转换成Foundation 其内存仍然需要手工管理的。
__bridge_retained 将一个Foundation对象转换成Core Foundation对象,并且ARC交出所有权
__bridge_transfer 将一个Core Foundation 对象转换成 Foundation并且 ARC 会获得 其所有权
...
CFStringRef cstr = CFStringCreateWithString(NULL, "Hello, World!", KCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:cstr];
NSLog(@"%d", [data count]);
...
这段代码无法编译
当我们使用ARC桥接时
...
CFStringRef cstr = CFStringCreateWithString(NULL, "Hello, World!", KCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:(__bridge NSString *)cstr];
NSLog(@"%d", [data count]);
...
虽然可以编译,但是会发生内存泄漏,此时ARC没有 cstr的所有权,无法进行内存释放, 当我们Analyze是Xcode会告知我们
所有 我们要在最后 CFrelase(cstr); 当然我们也可以用 __bridge_transfer
同理 将Foundation 对象转换成 Core Foundation时, 如果只使用_bridge 会发生野指针问题, 因此一旦将对象类型转换后, ARC会向其对象发送一个release,所以最好还是用__bridge_retained.