Managing Toll-Free Bridging

来源:互联网 发布:端口号20 编辑:程序博客网 时间:2024/05/23 19:51

在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检测,没有内存泄漏。

image

下面把上面工程改为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检测,可以发现内存泄漏:

image

由于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.
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 杭州驾照过期1年怎么办 驾驶证过期5个月怎么办 驾驶证过期3年了怎么办 c驾驶证换证过期怎么办 驾驶证过了两年怎么办 驾驶证过期8个月怎么办 学驾照快过期了怎么办 朋友开我车撞了怎么办 b2驾照扣分没审怎么办 驾驶证脱审2个月怎么办 驾驶证脱审1月怎么办 驾照过期了没换怎么办 驾照过期1年多了怎么办 考驾照科目一考不过怎么办 我考驾照过期了怎么办 驾照过了审验期怎么办 驾照过期3年了怎么办 如果学车过期了怎么办 行驶证过期了3年怎么办 行驶证过期没审怎么办 行驶证过期两年怎么办 驾驶证过期7年了怎么办 换驾照过一个月怎么办? 行驶证正本掉了怎么办 车的行驶证丢了怎么办 三星s6 屏幕坏了怎么办 手机摔成黑屏了怎么办 三星屏幕漏液了怎么办 三星s8屏幕漏液怎么办 屏幕紫色漏液了怎么办 华为手机屏碎了怎么办 小米2s按键失灵怎么办 魅蓝屏幕摔花了怎么办 小米手机屏碎了怎么办 厦门医保卡坏了怎么办 医保卡丢了北京怎么办 重庆社保卡丢了怎么办 沈阳医保卡丢了怎么办 小孩医保卡丢了怎么办 少儿医保卡丢了怎么办 孩子医保卡丢了怎么办