iOS开发之__bridge,__bridge_transfer和__bridge_retained

本文转至:http://www.qingpingshan.com/rjbc/ios/157477.html

引言

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

1.群体数据类型 (数组、集合等)

2.程序包

3.字符串管理

4.日期和时间管理

5.原始数据块管理

6.偏好管理

7.URL及数据流操作

8.线程和RunLoop

9.端口和soket通讯

Core Foundation框架和Foundation框架紧密相关,它们为相同功能提供接口,但Foundation框架提供Objective-C接口。如果您将Foundation对象和Core Foundation类型掺杂使用,则可利用两个框架之间的 “toll-free bridging”。所谓的Toll-free bridging是说您可以在某个框架的方法或函数同时使用Core Foundatio和Foundation 框架中的某些类型。很多数据类型支持这一特性,其中包括群体和字符串数据类型。每个框架的类和类型描述都会对某个对象是否为 toll-free bridged,应和什么对象桥接进行说明。

Toll-free bridging 是ARC下OC对象和Core Foundation对象之间的桥梁

在开发iOS应用程序时我们有时会用到Core Foundation对象,下面简称CF。例如Core Graphics、Core Text,并且我们可能需要将CF对象和OC对象进行相互转化,我们知道,ARC环境下,编译器不会自动管理CF对象的内存,我们需要手动管理。这就是我们在创建一个CF对象以后需要我们使用CFRelease将其手动释放。

那么CF和OC相互转化的时候该如何管理内存呢?

我们可以通过 bridge, bridge_transfer,__bridge_retained 来进行内存管理

1.__bridge

CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化

//Image I/O 从 NSBundle 读取图片数据
   NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"];
    CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"]], NULL);

如果上面不添加 bridge ,在ARC环境下,系统会给出错误提示和错误修正,点击错误提示的话,系统会为我们自动添加 bridge ,因为在OC与CF的转化时只涉及到对象类型没有涉及到对象所有权的转化,所以上述代码不需要对CF的对象进行释放,即不需要添加CFRelease

注释: iOS ARC 和 非ARC 之间的转换方法
1,选择项目中的Targets,选中你所要操作的Target,
2,选Build Phases,在其中Complie Sources中选择需要ARC的文件双击,
     并在输入框中输入:-fobjc-arc,如果不要ARC则输入:-fno-objc-arc

为了解决这一问题,我们使用 __bridge 关键字来实现id类型与void*类型的相互转换。

id obj = [[NSObject alloc] init];
    void *p = (__bridge void *)(obj);
    NSLog(@"obj retainCount %ld",[(id)p retainCount]);

输出结果:

CFDemo[2932:777997] obj retainCount 1

2.__bridge_transfer

常用在CF对象转化成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存,作用同CFBridgingRelease()

如果非ARC的时候,我们可能需要写下面的代码。

// p 变量原先持有对象的所有权
id obj = (id)p;
[obj retain];
[(id)p release];

那么ARC有效后,我们可以用下面的代码来替换:

// p 变量原先持有对象的所有权
id obj = (__bridge_transfer id)p;

可以看出来, bridge_retained 是编译器替我们做了 retain 操作,而 bridge_transfer 是替我们做了 release。

3.

bridge_retained

bridge_transfer 相反,常用在将OC对象转化成CF对象,且OC对象的所有权也交给CF对象来管理,即OC对象转化成CF对象时,涉及到对象类型和对象所有权的转化,作用同CFBridgingRetain()

先来看使用 __bridge_retained 关键字的例子程序:

id obj = [[NSObject alloc] init];
void *p = (__bridge_retained void *)obj;

此时retainCount 会被加1;

从名字上我们应该能理解其意义:类型被转换时,其对象的所有权也将被变换后变量所持有。如果不是ARC代码,类似下面的实现:

id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain];

ARC如何获取retainCount

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));

来来来举个例子:

NSString *string = [NSString stringWithFormat:@""];

    CFStringRef cfString = (__bridge CFStringRef)string;

    CFStringRef cfStr = (__bridge_retained CFStringRef)string;

    CFRelease(cfString);// 由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己release

    CFRelease(cfStr);

使用 __bridge_retained 可以通过转换目标处(cfStr)的 retain 处理,来使所有权转移。即使 string 变量被释放,cfString变量也变释放,cfStr 还是可以使用具体的对象。只是有一点,由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己release。

CFStringRef cfString= CFURLCreateStringByAddingPercentEscapes( NULL, (__bridge CFStringRef)text, NULL, CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
    NSString *ocString = (__bridge_transfer CFStringRef)cfString;

所有权被转移的同时,被转换变量将失去对象的所有权。当Core Foundation对象类型向Objective-C对象类型转换的时候,会经常用到 __bridge_transfer 关键字。

总结:

  1. Core Foundation 对象类型不在 ARC 管理范畴内
  2. Cocoa Framework::Foundation 对象类型(即一般使用到的Objectie-C对象类型)在 ARC 的管理范畴内 
    3. bridge, bridge_transfer和__bridge_retained 是CF和OC的桥梁
  3. 如果不在 ARC 管理范畴内的对象,那么要清楚 release 的责任应该是谁以及各种对象的生命周期是怎么样的

这是目前在学习ImageIO苹果官方提供的图片解码器,遇到OC和CF之间相互转化的一些问题,重新整理,细致的了解下,以方便后期更加深入的学习。

时间: 2025-01-02 19:00:27

iOS开发之__bridge,__bridge_transfer和__bridge_retained的相关文章

IOS开发之 __bridge __bridge_transfer和__bridge_retained

Core Foundation 框架 Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的服务: 群体数据类型 (数组.集合等) 程序包 字符串管理 日期和时间管理 原始数据块管理 偏好管理 URL及数据流操作 线程和RunLoop 端口和soket通讯 Core Foundation框架和Foundation框架紧密相关,它们为相同功能提供接口,但

iOS 开发之__bridge __bridge_retained 和 __bridge_transfer的区别

简介:__bridge:实现id类型与void*类型的相互转换: __bridge_retained:类型被转换时,其对象的所有权也将被变换后变量所持有 __bridge_transfer:类型被转换时,其对象的所有权也将被释放 __bridge_retained 是编译器替我们做了 retain 操作,而 __bridge_transfer 是替我们做了 release1. 详情: 在iOS世界,主要有两种对象:Objective-C 对象和 Core Foundation 对象0.Core

__bridge,__bridge_transfer和__bridge_retained详解

Core Foundation 框架Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的服务: 群体数据类型 (数组.集合等)程序包字符串管理日期和时间管理原始数据块管理偏好管理URL及数据流操作线程和RunLoop端口和soket通讯Core Foundation框架和Foundation框架紧密相关,它们为相同功能提供接口,但Foundation

ios开发中的toll-free bridged

所谓的Toll-free bridging是说您可以在某个框架的方法或函数 同时使用Core Foundatio和Foundation 框架中的某些类型. 很多数据类型支持这一特性,其中包括群体和字符串数据类型. 每个框架的类和类型描述都会对某个对象是否为 toll-free bridged, 应和什么对象桥接进行说明. 类型转换关键字区别: __bridge (相当于assign 还是要自己管理对象) __bridge_transfer(相当于copy后release   转让了自己对对象的所

iOS开发ARC内存管理技术要点

本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇文章不是一篇标准的ARC使用教程,并假定读者已经对ARC有了一定了解和使用经验.详细的关于ARC的信息请参见苹果的官方文档与网上的其他教程:) 本文的主要内容: ARC的本质 ARC的开启与关闭 ARC的修饰符 ARC与Block ARC与Toll-Free Bridging 技术交流新QQ群:41

iOS开发中的ARC内存管理de技术要点

本文旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇文章不是一篇标准的ARC使用教程,并假定读者已经对ARC有了一定了解和使用经验.详细的关于ARC的信息请参见苹果的官方文档与网上的其他教程:) 本文的主要内容: ARC的本质 ARC的开启与关闭 ARC的修饰符 ARC与Block ARC与Toll-Free Bridging ARC的本质 ARC是编译器(时)特性,而不是运行时

(转)iOS开发ARC内存管理技术要点

转自:http://www.cnblogs.com/flyFreeZn/p/4264220.html 本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇文章不是一篇标准的ARC使用教程,并假定读者已经对ARC有了一定了解和使用经验.详细的关于ARC的信息请参见苹果的官方文档与网上的其他教程:) 本文的主要内容: ARC的本质 ARC的开启与关闭 A

iOS开发tips总结

tip 1 :  给UIImage添加毛玻璃效果 func blurImage(value:NSNumber) -> UIImage { let context = CIContext(options:[KCIContextUseSoftwareRenderer:true]) let ciImage = CoreImage.CIImage(image:self) let blurFilter = CIFilter(name:"CIGassianBlur") blurFilter?

ios开发 部分内容整理

1.ViewController的生命周期 按结构可以对iOS的所有ViewController分成两类: 1.主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITableViewController,UIViewController. 2.用于控制和显示其他ViewController的ViewController.这种ViewController一般都是一个ViewController的容器.如UINavigation