很多時候都會使用到CoreFoundation的函數(shù),其返回值為CoreFoundation框架的對象,如果想轉(zhuǎn)換為Foundation框架的對象就可以使用橋接方式來搞定。
在Core Foundation框架和Foundation框架中有很多數(shù)據(jù)類型可以交替轉(zhuǎn)換。能夠被交替轉(zhuǎn)換的數(shù)據(jù)類型也被叫做Toll-Free Bridged數(shù)據(jù)類型。這意味著你能像參數(shù)一樣使用相同的數(shù)據(jù)結(jié)構對一個Core Foundation的函數(shù)進行調(diào)用,或者像Objective-C的消息接受模式一樣執(zhí)行。
Core Foundation內(nèi)存管理
編譯器并不會自動管理Core Foundation對象的生命周期。你必須告訴編譯器對象的語義所屬關系通過使用一種轉(zhuǎn)換(定義在objc/runtime.h)或者Core Foundation風格的宏(定義在 NSObject.h)。
1. __bridge
- CF和OC對象轉(zhuǎn)化時,只涉及對象類型,不涉及對象所有權的轉(zhuǎn)化。
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge CFURLRef)url;
- 當使用
__bridge標識符以后,OC創(chuàng)建的對象并且在轉(zhuǎn)換時沒有涉及對象所有權的轉(zhuǎn)換,所以上面的代碼不需要加CFRelease()。
2. __bridge_retained
- 常用在將OC對象轉(zhuǎn)化成CF對象,且OC對象的所有權也交給CF對象來管理,即OC對象轉(zhuǎn)化成CF對象時,涉及到對象類型和對象所有權的轉(zhuǎn)化。作用同
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對象轉(zhuǎn)化成OC對象時,將CF對象的所有權交給OC對象,此時ARC就能自動管理該內(nèi)存。作用同
CFBridgingRelease()。
CFStringRef cfString= CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)text,
NULL,
CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
NSString *ocString = (__bridge_transfer CFStringRef)cfString;
- 此時OC即獲得了對象的所有權,ARC負責自動釋放該對象,如果我們在結(jié)尾加上
CFRelease(cfString)純屬畫蛇添足,雖不會崩潰,但是控制臺會打印出該對象被free了兩次。
要點
通過無縫橋接技術,可以在Foundation框架中的Objective-C對象與CoreFoundation框架中的C語言數(shù)據(jù)結(jié)構之間來回轉(zhuǎn)換。
在CoreFoundation層面創(chuàng)建collection時,可以指定許多回調(diào)函數(shù),這些函數(shù)表示此collection應如何處理其元素。然后,可運用無縫橋接技術,將其轉(zhuǎn)換成具備特殊內(nèi)存管理語義的Objective-C collection。