52个有效方法(49) - 对自定义其内存管理语义的collection使用无缝桥接

很多时候都会使用到CoreFoundation的函数,其返回值为CoreFoundation框架的对象,如果想转换为Foundation框架的对象就可以使用桥接方式来搞定。

Core Foundation框架和Foundation框架中有很多数据类型可以交替转换。能够被交替转换的数据类型也被叫做Toll-Free Bridged数据类型。这意味着你能像参数一样使用相同的数据结构对一个Core Foundation的函数进行调用,或者像Objective-C的消息接受模式一样执行。

Core Foundation内存管理

编译器并不会自动管理Core Foundation对象的生命周期。你必须告诉编译器对象的语义所属关系通过使用一种转换(定义在objc/runtime.h)或者Core Foundation风格的宏(定义在 NSObject.h)。

1. __bridge
  • CF和OC对象转化时,只涉及对象类型,不涉及对象所有权的转化。
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge CFURLRef)url;
  • 当使用__bridge标识符以后,OC创建的对象并且在转换时没有涉及对象所有权的转换,所以上面的代码不需要加CFRelease()
2. __bridge_retained
  • 常用在将OC对象转化成CF对象,且OC对象的所有权也交给CF对象来管理,即OC对象转化成CF对象时,涉及到对象类型和对象所有权的转化。作用同CFBridgingRetain()
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge_retained CFURLRef)url;
CFRelease(ref);
  • 当使用_bridge_retained标识符以后,代表OC要将对象所有权交给CF对象自己来管理,所以我们要在ref使用完成以后用CFRelease()将其手动释放。
2. __bridge_transfer
  • 常用在CF对象转化成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存。作用同CFBridgingRelease()
CFStringRef cfString= CFURLCreateStringByAddingPercentEscapes(
                                                                  NULL,
                                                                  (__bridge CFStringRef)text,
                                                                  NULL,
                                                                  CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
NSString *ocString = (__bridge_transfer CFStringRef)cfString;
  • 此时OC即获得了对象的所有权,ARC负责自动释放该对象,如果我们在结尾加上CFRelease(cfString)纯属画蛇添足,虽不会崩溃,但是控制台会打印出该对象被free了两次
要点
  1. 通过无缝桥接技术,可以在Foundation框架中的Objective-C对象与CoreFoundation框架中的C语言数据结构之间来回转换。

  2. 在CoreFoundation层面创建collection时,可以指定许多回调函数,这些函数表示此collection应如何处理其元素。然后,可运用无缝桥接技术,将其转换成具备特殊内存管理语义的Objective-C collection。

你可能感兴趣的:(52个有效方法(49) - 对自定义其内存管理语义的collection使用无缝桥接)