Foundation和Core Foundation掺杂使用桥接 Toll-Free Bridging
生活随笔
收集整理的這篇文章主要介紹了
Foundation和Core Foundation掺杂使用桥接 Toll-Free Bridging
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在cocoa application的應用中,我們有時會使用Core Foundation(CF),我們經常會在Objective-C和CF之間進行轉化。系統使用arc的狀態下,編譯器不能自動管理CF的內存,這時候你必須使用CFRetain和CFRelease來進行CF的內存的管理。
具體的CF內存管理規則見: Memory Management Programming Guide for Core Foundation
在OC和FC之間進行轉化的時候,主要是對象的歸屬問題。共有兩種方式:
1、使用宏,可以標識歸屬者從OC到CF,還是從CF到OC。
NS_INLINE CFTypeRef CFBridgingRetain(id X) {?
return (__bridge_retain CFTypeRef)X;?
}?
NS_INLINE id CFBridgingRelease(CFTypeRef X) {?
return (__bridge_transfer id)X;?
}
2、使用轉化符,如:__bridge,__bridge_transfer,__bridge_retained
id my_id;?
CFStringRef my_cfref;?
…?
NSString ? *a = (__bridge NSString*)my_cfref; ? ? // Noop cast.?
CFStringRef b = (__bridge CFStringRef)my_id; ? ? ?// Noop cast.?
…?
NSString ? *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef?
CFStringRef d = (__bridge_retained CFStringRef)my_id; ?// returned CFRef is +1
下面以詳細的例子來介紹一下OC和CF在arc下內存管理的詳細寫法.下面以CFURLCreateStringByAddingPercentEscapes()函數為例說一下在ARC下的寫法和非ARC下的寫法。
非ARC模式下的寫法:
#pragma mark – View lifecycle?
- (void)viewDidLoad?
{?
[super viewDidLoad];?
NSLog(@"=%@", [self escape:@"wangjun"]);?
}?
-(NSString *)escape:(NSString *)text?
{?
return (NSString *)CFURLCreateStringByAddingPercentEscapes(?
NULL,?
(__bridge CFStringRef)text,?
NULL,?
CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));;?
}
使用instruments檢測,沒有內存泄漏。
下面把上面工程改為arc模式。
可以看到xcode自動把上面函數轉化為:
#pragma mark – View lifecycle?
- (void)viewDidLoad?
{?
[super viewDidLoad];?
NSLog(@"=%@", [self escape:@"wangjun"]);?
}?
-(NSString *)escape:(NSString *)text?
{?
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(?
NULL,?
(__bridge CFStringRef)text,?
NULL,?
CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));;?
}
在arc中,CF和OC之間的轉化橋梁是 __bridge,有兩種方式:
__bridge_transfer ?ARC接管管理內存
__bridge_retained ?ARC釋放內存管理
上面的方法是從CF轉化為OC NSString對象,使用的__bridge_transfer ,對象所有者發生轉變,由CF到OC,最后由ARC接管內存管理。運行上面的代碼,用instruments檢測,是沒有內存泄漏的。
上面代碼等同于:
- (NSString *)escape:(NSString *)text?
{?
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(?
NULL,?
(__bridge CFStringRef)text,?
NULL,?
CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)));}
如果將上述代碼改為:
-(NSString *)escape:(NSString *)text?
{?
return (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(?
NULL,?
(__bridge CFStringRef)text,?
NULL,?
CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));;?
}
編譯也會成功,但是這時候用instruments檢測,可以發現內存泄漏:
由于CF轉化完OC,沒有自己釋放內存,同時也沒有把內存管理交給ARC,所以出現內存泄漏。由于__bridge只是同一個對象的引用,內存的所有權沒有發生變化。
下面在說一下oc到CF的轉化,需要把OC的內存管理權釋放掉。
NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];?
CFStringRef s2 = (__bridge_retained CFStringRef)s1;?
// do something with s2 // . . .?
CFRelease(s2);
最后由CF進行內存釋放。
上面代碼等同于:
CFStringRef s2 = CFBridgingRetain(s1);?
// . . .?
CFRelease(s2);
下面總結一下我們使用ARC情況下。oc和CF互相轉化的原則:
CF轉化為OC時,并且對象的所有者發生改變,則使用CFBridgingRelease()或__bridge_transfer 。
OC轉化為CF時,并且對象的所有者發生改變,則使用CFBridgingRetain()或__bridge_retained
當一個類型轉化到另一種類型時,但是對象所有者沒有發生改變,則使用__bridge.
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的Foundation和Core Foundation掺杂使用桥接 Toll-Free Bridging的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dnf贝奇NPC位置在哪里 dnf贝奇N
- 下一篇: 全民坦克大战各坦克技能属性详解