http://blog.csdn.net/shencaifeixia1/article/details/8147117
__bridge:不涉及對象所有關係改變__bridge_transfer:給予 ARC 所有權
__bridge_retained:解除 ARC 所有權
形式:
(__bridge type)expression;
(__bridge_retained CF_type)expression;
(__bridge_transfer Objective-C type)expression;
涉及到被轉換對象指標和轉換對象指標指向的共同記憶體的釋放問題。要小心記憶體泄露;一般__bridge_retained只用於OC對象到非OC對象的轉換;__bridge可以互相轉換;__bridge_transfer只能用於非OC對象到OC對象的轉換。
在ARC中,OC對象與非OC對象在強制轉換中,需要使用以上三個關鍵字進行橋接,那麼三個關鍵字各用在什麼情況下呢?詳解如下:
下面一行代碼:
CFStringRef s1 = (CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];
在ARC下面會報編譯問題,並會給出推薦的解決方案:
CFStringRef s1 = (__bridge CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];
這裡NSString產生的是OC的對象,記憶體由ARC負責。s1是CF的對象,記憶體還是需要自己手動管理。兩個變數轉換時需要添加橋接標識。
上面這種情況下不會crash,也不會有記憶體泄露。因為alloc出來的記憶體會被ARC回收,這塊記憶體的所有關係沒變。
如果後面加上CFRelease(s1);就會crash,因為這塊記憶體還是歸ARC管的,這樣會過度釋放。
修改一下:CFStringRef s1 = (__bridge_retained CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];
這種情況下,對象的所有權交給CF對象了。就需要加上CFRelease(s1);進行釋放,否則會產生泄露。
再看下面代碼:CFUUIDRef uu = CFUUIDCreate(NULL);
CFStringRef s2 = CFUUIDCreateString(NULL, uu);
CFRelease(uu);
NSString* str = (__bridge NSString*)s2;NSLog(@”STR:%@”,str);
CFRelease(s2);
這裡的uu和s2都需要使用CFRelease釋放,因為他們不是OC對象,並且是create出來的記憶體,並且所有權沒有被釋放。
如果改動下面一行代碼:NSString* str = (__bridge_transfer NSString*)s2;
這時候運行程式會引起crash,因為s2的所有權已經交給ARC中的str了,ARC會負責釋放這塊記憶體。
這時候調用CFRelease(s2);會造成過度釋放。所以應該把這麼行代給去了。
註:ARC模式下,自動回收只針對Objective-C對象有效,對於使用create,copy,retain等產生的Core Foundation對象還是需要我們手動進行釋放的,CFRelease().關於_bridge總結:(1)OC對象 -> 非OC對象:不涉及對象所有權的轉移,即該記憶體的所有權還是由ARC來處理;(2)非OC對象 -> OC對象:不涉及對象所有權的轉移,即該記憶體的所有權還是由非OC對象來處理;