zoukankan      html  css  js  c++  java
  • IOS

    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.
  • 相关阅读:
    Hive的mysql安装配置
    Linux下的MySQL安装
    Hive的安装与基础指令
    浅谈数据库和数据仓库
    Hive的学习之路(理论篇)
    Spring---bean的命名
    Spring---单例模式(Singleton)的6种实现
    Spring---加载配置文件的几种方法(org.springframework.beans.factory.BeanDefinitionStoreException)
    Spring---配置文件概述
    Spring---Bean生命周期
  • 原文地址:https://www.cnblogs.com/mcj-coding/p/3581513.html
Copyright © 2011-2022 走看看