Foundation 對象是Objective-C對象,使用Objective-C語言實現(xiàn);而Core Foundation對象是C對象,使用C語言實現(xiàn)。兩者之間可以通過__bridge、__bridge_transfer、__bridge_retained 等關(guān)鍵字轉(zhuǎn)換(橋接)。
Foundation對象和 Core Foundation 對象更重要的區(qū)別是ARC下的內(nèi)存管理問題。在非ARC下兩者都需要開發(fā)者手動管理內(nèi)存,沒有區(qū)別。但在ARC下,系統(tǒng)只會自動管理Foundation對象的釋放,而不支持對 Core Foundation 對象的管理。因此,在ARC下兩者進(jìn)行轉(zhuǎn)換后,必須要確定轉(zhuǎn)換后的對象是由開發(fā)者手動管理,還是由ARC系統(tǒng)繼續(xù)管理,否則可能導(dǎo)致內(nèi)存泄漏問題。
下面以NSString對象(Foundation 對象)和CFStringRef 對象(Core Foundation 對象)為例,介紹兩者的轉(zhuǎn)換和內(nèi)存管理權(quán)移交問題。
(1)在非ARC下,NSString 對象和 CFStringRef對象可以直接進(jìn)行強(qiáng)制轉(zhuǎn)換,都是手動管理內(nèi)存,無須關(guān)心內(nèi)存管理權(quán)的移交問題。
(2)在ARC下,NSString 對象和CFStringRef對象在相互轉(zhuǎn)換時,需要選擇使用__bridge、__bridge_transfer 和__bridge_retained來確定對象的管理權(quán)轉(zhuǎn)移問題,三者的作用話義介如下:
-
__bridge關(guān)鍵詞最常用,它的含義是不改變對象的管理權(quán)所有者,本來由ARC管理的Foundation對象,轉(zhuǎn)換成Core Foundation對象后依然由ARC管理;本來由開發(fā)者手動管理的Core Foundation對象轉(zhuǎn)換成Foundation對象后繼續(xù)由開發(fā)者手動管理。示例代碼如下:/* ARC 管理的Foundation對象*/ NSString *s1 = @"string"; /* 轉(zhuǎn)換后依然由ARC管理釋放 */ CFStringRef cfstring = (__bridge CFStringRef)s1; /* 開發(fā)者手動管理的Core Foundation對象*/ CFStringRef s2 = CFStringCreateWithCString(NULL, "string", KCFStringEncodingASCI); /* 轉(zhuǎn)換后仍然需要開發(fā)者手動管理釋放*/ NSString * fstring = __bridge NSString*)s2; -
__bridge_transfer用在將Core Foundation對象轉(zhuǎn)換成Foundation對象時,用于進(jìn)行內(nèi)存管理權(quán)的移交,即本來需由開發(fā)者手動管理釋放的Core Foundation對象在轉(zhuǎn)換成Foundation對象后,交由ARC來管理對象的釋放,開發(fā)者不用再關(guān)心對象的釋放問題,因為不會發(fā)生內(nèi)存泄漏。示例代碼如下:/* 開發(fā)者手動管理的Core Foundation對象*/ CFStringRef s2 = CFStringCreateWithCString(NULL, "string", kCFStringEncodingASCII); /* 轉(zhuǎn)換后改由 ARC 管理對象的釋放,不用擔(dān)心內(nèi)存泄漏*/ NSString *fstring = (__bridge_transfer NSString*)s2; //NSString *fstring = (NSString*)CFBridgingRelease(s2);//另一種等效寫法 -
__bridge_retained用在將Foundation對象轉(zhuǎn)換成Core Foundation對象時,進(jìn)行ARC內(nèi)存管理權(quán)的剝奪,即本來由ARC管理的Foundation對象在轉(zhuǎn)換成Core Foundation對象后,ARC不再繼續(xù)管理該對象,需要開發(fā)者白己進(jìn)行手動釋放該對象,否則會發(fā)生內(nèi)存泄漏。示例代碼如下:/* ARC 管理的 Foundation 對象*/ NSString *s1 = @"string"; /* 轉(zhuǎn)換后 ARC 不再繼續(xù)管理,需要手動釋放*/ CFStringRef cfstring = (__bridge_retained CFStringRef)s1; //CFStringRef cfstring = (CFStringRef)CFBridgingRetain(s1);//另一種等效寫法