(1)Foundation與Core Foundation對象
? ? Foundation對象就是使用Object-C創(chuàng)建出來的對象(一般以NS開頭), Core Foundation對象主要是使用C語言創(chuàng)建的對象(一般以CF開頭)铸敏,兩個框架創(chuàng)建的對象都使用引用計數(shù)管理內(nèi)存杈笔。在MRC環(huán)境下,Core Foundation框架中的retain/release分別是CFRetain/CFRelease禁筏。Core Foundation 與 Foundation 框架創(chuàng)建出來的對象區(qū)別很小,可以在不同的框架中使用旱爆,F(xiàn)oundation框架的API生成并持有的對象可以用Core Foundation框架的API釋放,反過來也可以邢羔。
? ? 因為Core Foundation對象與Foundation對象沒有區(qū)別拜鹤,轉(zhuǎn)換不需要額外的CPU資源宣虾,因此也被稱為“免橋接”Toll - Free - Bridge绣硝。
(2)顯示轉(zhuǎn)換id 和 void*
/* MRC環(huán)境下 轉(zhuǎn)換*/
<pre>
id obj = [[NSObject alloc] init];
void *p = obj;
id o = p;
[o release];
</pre>
/*ARC環(huán)境下 轉(zhuǎn)換*/
? ? 在ARC環(huán)境下上面代碼會引起編譯錯誤,(個人猜測MRC下Foundation與Core Foundation對象都需要手動管理挠铲,而ARC環(huán)境下Foundation對象內(nèi)存不需要手動管理Core Foundation對象需要刹衫,所以不能直接轉(zhuǎn)需要橋接)
<pre>
id obj = [[NSObject alloc] init];
void *p = (__bridge void *)obj;
id o = (__bridge id)p;
</pre>
? ? 但是__bridge并不轉(zhuǎn)讓對象所有者音羞,其安全性和__unsafe_unretained修飾符相近搀继,甚至更低,如果不注意對象持有者會引起懸垂指針叽躯。橋接轉(zhuǎn)換還有另外兩種方式财边,分別是__bridge_retained和__bridge_transfer轉(zhuǎn)換
__bridge_retained轉(zhuǎn)換可使要轉(zhuǎn)換賦值的變量也持有所賦值的對象。在MRC下其源代碼是:
<pre>
id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain];
</pre>
ARC環(huán)境下可以寫成:
<pre>
void *p = 0;
{
id obj = [[NSObject alloc] init];
p = (__bridge_retained void *)obj;
}
NSLog(@“class = %@“, [(__bridge id) p]);
</pre>
? ? obj變量作用域雖然結(jié)束了点骑,但是由于__bridge_retained轉(zhuǎn)換使p處于持有該對象的狀態(tài)酣难,因此對象不會被釋放谍夭,用完需要手動釋放p。
__briege_transfer轉(zhuǎn)換提供與__bridge_retained相反的動作憨募,被轉(zhuǎn)換的變量所持有的對象在改變量賦值后會隨之釋放紧索。
id obj = (__bridge_transfer id)p;
/*在MRC下表述為*/
<pre>
id obj = (id)p
[obj retain];
[(id)p release];
</pre>
(3)Foundation與Core Foundation對象轉(zhuǎn)換 (終于講到重點了)
** Foundation ——> Core Foundation
/*MRC環(huán)境下*/
<pre>
CFMutableArrayRef cfobject = NULL;
{
id obj = [[NSMutableArray alloc] init];
[obj retain]
cfObject = (CFMutableArrayRef)obj;
CFRetain(cfobject); //記得持有對象
[obj release];
}
CFShow(cfObject);
CFRelease(cfObject);
</pre>
/*ARC環(huán)境下*/
<pre>
CFMutableArrayRef cfobject = NULL;
{
id obj = [[NSMutableArray alloc] init];//ARC下obj內(nèi)存管理修飾符默認為__string,所以obj將持有對象
cfObject = (__bridge_retained? CFMutableArrayRef)obj;?//cfobject已經(jīng)持有對象
}
//超出作用域菜谣,obj釋放珠漂,但是cfobject還持有對象,所以對象不會釋放(ARC管理Foundation對象不管理Core Foundation對象內(nèi)存)
CFShow(cfObject);
CFRelease(cfObject);
</pre>
**Core Foundation ——> Foundation
/*MRC環(huán)境下*/
<pre>
{
CFMutableArrayRef cfObject = CFArrayCreateMutable(KCFAllocatorDefault, 0, NULL);
id obj = (id)cfObject;
[obj retained];
CFRelease(cfobject);
NSLog(@“clase=%@“, obj);
[obj release];//此時對象不再擁有持有者尾膊,將被釋放
}
</pre>
/*ARC環(huán)境下*/
<pre>
{
CFMutableArrayRef cfObject = CFArrayCreateMutable(KCFAllocatorDefault, 0, NULL);
id obj = (__bridge_transfer id)cfObject; //對象賦值完成后cfObject不在持有對象引用將被釋放媳危,但是obj默認修飾符為__strong,所以obj將持有對象
NSLog(@“clase=%@“, obj);
}
</pre>
//超出作用域眯停,obj釋放,此時對象不再擁有持有者卿泽,將被釋放莺债。
個人總結(jié)下:__bridge_retained是在橋接后讓Core Foundation對象變量持有對象,即讓對象引用計數(shù)+1签夭,__bridge_transfer橋接后讓Core Foundation對象變量釋放所持有的對象齐邦,即讓對象引用計數(shù)-1。而__bridge除了橋接其他什么操作都不做第租。在ARC環(huán)境下措拇,下面的操作是對等的:
cfObject = (__bridge CFMutableArrayRef)obj + CFRetain(cfObject) ?與?cfObject = (__bridge_retained CFMutableArrayRef)obj
obj = (__bridge id)cfObject + CFRelease(cfObject) 與?obj = (__bridge_transfer id)cfObject