当前位置:编程学习 > 网站相关 >>

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];&nb
补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,