52个有效方法(49) - 对自定义其内存管理语义的collec
2018-10-09 本文已影响15人
SkyMing一C
很多时候都会使用到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了两次
。
要点
-
通过无缝桥接技术,可以在Foundation框架中的Objective-C对象与CoreFoundation框架中的C语言数据结构之间来回转换。
-
在CoreFoundation层面创建collection时,可以指定许多回调函数,这些函数表示此collection应如何处理其元素。然后,可运用无缝桥接技术,将其转换成具备特殊内存管理语义的Objective-C collection。