Core Foundation不支持ARC,那么在做Core Foundation與Objective-C類型轉換的時候就需要考慮以何種規則來管理對象的內存。
__bridge(修飾符)
只是聲明類型轉變,但是不做內存管理規則的轉變。
例:
CFStringRef s1 = (__bridge CFStringRef) [[NSString alloc] initWithFormat:@"Hello, %@!", name];
只是做了NSString到CFStringRef的轉化,但管理規則未變,依然要用Objective-C類型的ARC來管理s1,你不能用CFRelease()去釋放s1。
__bridge_retained(修飾符) or CFBridgingRetain(函數)
表示將指針類型轉變的同時,將內存管理的責任由原來的Objective-C交給Core Foundation來處理,也就是,將ARC轉變為MRC。
例:
NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];
CFStringRef s2 = (__bridge_retained CFStringRef)s1;
// or CFStringRef s2 = (CFStringRef)CFBridgingRetain(s1);
// do something with s2
//...
CFRelease(s2); // 注意要在使用結束后加這個
在第二行做了轉化,這時內存管理規則由ARC變為了MRC,需要手動的來管理s2的內存,而對于s1,即使將其置為nil,也不能釋放內存。
__bridge_transfer(修飾符) or CFBridgingRelease(函數)
這個修飾符和函數的功能和上面那個__bridge_retained相反,它表示將管理的責任由Core Foundation轉交給Objective-C,即將管理方式由MRC轉變為ARC。
例:
CFStringRef result = CFURLCreateStringByAddingPercentEscapes(. . .);
NSString *s = (__bridge_transfer NSString *)result;
//or NSString *s = (NSString *)CFBridgingRelease(result);
return s;
這里將result的管理責任交給了ARC來處理,就不需要再顯式地調用CFRelease()了。
所以,bridge相關的修飾符or函數,名稱里包含retain
的,就是將ARC轉為MRC(由OC轉為Core Foundation機制),此時需要我們手動管理內存,在對象使用完畢后,需要主動調用對應的release方法。
參考文章:iOS開發ARC內存管理技術要點