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.

IOS - Foundation和Core Foundation掺杂使用桥接的更多相关文章

  1. IOS开发之—— Core Foundation对象与OC对象相对转换的问题

    对ARC盲目依赖的同学: 1过度使用block后,无法解决循环引用问题 2遇到底层Core Foundation对象,需要自己手工管理它们的引用计数时,显得一筹莫展 first:对于底层Core Fo ...

  2. Foundation与Core Foundation内存管理基本原则简述

    内存管理是一个十分重要的事情,稍有不慎就会发生内存泄漏或者是野指针的错误.内存泄漏一般表示没有任何指针指向的内存区域,由于这块内存在对象图中无法查找到,所以有可能永远都无法回收,如果内存泄漏的空间比较 ...

  3. Core Foundation框架介绍

    Core Foundation框架介绍 **参考网址: ARC下OC对象和CF对象之间的桥接 Core Foundation框架介绍 Core Foundation框架 Core Foundation ...

  4. Core Foundation 官方文档翻译

      Core Foundation框架中常用的隐含类型: 使用这些隐含类型时需要自己初始化,自己去释放内存.所以需要记住,在初始化的同时在相应位置释放.以防出现内存问题.   1.CFStringRe ...

  5. iOS-Core Foundation框架到Foundation桥接的三种方式

    温故知新.勤总结,才能生巧!这次总结一下 :Core Foundation框架到Foundation桥接的三种方式 Foundation提供OC的基础类(像NSObject).基本数据类型等. Cor ...

  6. IOS之Core Foundation框架和Cocoa Foundation框架的区别

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

  7. IOS之Core Foundation框架和Cocoa Foundation框架的区别(转)

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

  8. Core Foundation框架

    转载自:http://blog.csdn.net/weiwangchao_/article/details/7744972 Core Foundation框架 (CoreFoundation.fram ...

  9. Core Foundation 框架

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

随机推荐

  1. solr

    一.启动命令 tar -zxvf solr-.tgz cd solr-\example java -jar start.jar 默认监听8983端口 java -Djetty.port= -jar s ...

  2. qt 的简介与使用

    1.图形类的构造,都是通过类的构造函数以及界面初始化这两部分 2.在qtcreator的界面编辑器通过“提升类”的方法,要确定头文件的路径是否正确 3.点击窗口关闭时,销毁窗口内容时,设置属性-> ...

  3. Hibernate get和load区别

    1.从返回结果上对比:load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常get方法检索不到的话会返回null   2.从检索执行机制上对比: ...

  4. .net生成二维码

    下好QRCode.dll引用到项目中 using System; using System.Collections.Generic; using System.Linq; using System.W ...

  5. Web服务精讲–搭个 Web 服务器(二)

    导读 曾几何时,你所选择的 Python Web 框架会限制你所可选择的 Web 服务器,反之亦然.如果某个框架及服务器设计用来协同工作的,那么一切正常. 在第一部分中,我提出了一个问题:“如何在你刚 ...

  6. Unity3D中脚本的执行顺序和编译顺序

    http://www.cnblogs.com/champ/p/execorder.html 在Unity中可以同时创建很多脚本,并且可以分别绑定到不同的游戏对象上,它们各自都在自己的生命周期中运行.与 ...

  7. [codeforces 339]C. Xenia and Weights

    [codeforces 339]C. Xenia and Weights 试题描述 Xenia has a set of weights and pan scales. Each weight has ...

  8. 教你搭建SpringSecurity3框架( 更新中、附源码)

    源码下载地址:http://pan.baidu.com/s/1qWsgIg0 一.web.xml <?xml version="1.0" encoding="UTF ...

  9. 剑指Offer 栈的压入、弹出序列

    题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...

  10. caffe学习系列(7):Blob,layer,Net介绍

    参考:http://www.cnblogs.com/denny402/p/5073427.html