Core Foundation 对象不属于ARC的管辖范围
来源:互联网 发布:尔雅网络课 编辑:程序博客网 时间:2024/06/11 20:44
我们先来看一下ARC无效的时辰,我们写id类型转void*类型的写法:
12
id obj = [[NSObject alloc] init];void *p = obj;
反过来,当把void*对象变回id类型时,只是简单地如下来写,
12
id obj = p;[obj release];
然则上方的代码在ARC有效时,就有了下面的错误:
error: implicit conversion of an Objective-C pointer to ’void *’ is disallowed with ARC void *p = obj; ^ error: implicit conversion of a non-Objective-C pointer type ’void *’ to ’id’ is disallowed with ARC id o = p; ^
__bridge
为懂得决这一题目,我们应用?__bridge?关键字来实现id类型与void*类型的彼此转换。看下面的例子。
12345
id obj = [[NSObject alloc] init];void *p = (__bridge void *)obj;id o = (__bridge id)p;
将Objective-C的对象类型用 __bridge 转换为 void* 类型和应用 __unsafe_unretained 关键字润饰的变量是一样的。被代入对象的所有者须要明白对象生命周期的经管,不要呈现异常接见的题目。
除过 __bridge 以外,还有两个 __bridge 相干的类型转换关键字:
- __bridge_retained
- __bridge_transfer
接下来,我们将看看这两个关键字的差别。
__bridge_retained
先来看应用 __bridge_retained 关键字的例子法度:
123
id obj = [[NSObject alloc] init];void *p = (__bridge_retained void *)obj;
从名字上我们应当能懂得其意义:类型被转换时,其对象的所有权也将被变换后变量所持有。若是不是ARC代码,类似下面的实现:
1234
id obj = [[NSObject alloc] init];void *p = obj;[(id)p retain];
可以用一个实际的例子验证,对象所有权是否被持有。
12345678
void *p = 0;{ id obj = [[NSObject alloc] init]; p = (__bridge_retained void *)obj;}NSLog(@"class=%@", [(__bridge id)p class]);
出了大括号的局限后,p 仍然指向一个有效的实体。申明他拥有该对象的所有权,该对象没有因为出其定义局限而被烧毁。
__bridge_transfer
相反,当想把底本拥有对象所有权的变量,在类型转换后,让其开释本来所有权的时辰,须要应用 __bridge_transfer 关键字。文字有点绕口,我们还是来看一段代码吧。
若是ARC无效的时辰,我们可能须要写下面的代码。
1234
// p 变量本来持有对象的所有权id obj = (id)p;[obj retain];[(id)p release];
那么ARC有效后,我们可以用下面的代码来调换:
12
// p 变量本来持有对象的所有权id obj = (__bridge_transfer id)p;
可以看出来,__bridge_retained 是编译器替我们做了 retain 操纵,而 __bridge_transfer 是替我们做了 release1。
Toll-Free bridged
在iOS世界,首要有两种对象:Objective-C 对象和 Core Foundation 对象0。Core Foundation 对象主如果有C说话实现的 Core Foundation Framework 的对象,此中也有对象引用计数的概念,只是不是 Cocoa Framework::Foundation Framework 的 retain/release,而是自身的 CFRetain/CFRelease 接口。
这两种对象间可以互相转换和操纵,不应用ARC的时辰,纯真的用C原因的类型转换,不须要消费CPU的资料,所以叫做 Toll-Free bridged。比如 NSArray和CFArrayRef, NSString和CFStringRef,他们固然属于不合的 Framework,然则具有雷同的对象布局,所以可以用标准C的类型转换。
比如不应用ARC时,我们用下面的代码:
12
NSString *string = [NSString stringWithFormat:...];CFStringRef cfString = (CFStringRef)string;
同样,Core Foundation类型向Objective-C类型转换时,也是简单地用标准C的类型转换即可。
然则在ARC有效的景象下,将呈现类似下面的编译错误:
Cast of Objective-C pointer type ‘NSString *’ to C pointer type ‘CFStringRef’ (aka ‘const struct __CFString *’) requires a bridged cast Use __bridge to convert directly (no change in ownership) Use __bridge_retained to make an ARC object available as a +1 ‘CFStringRef’ (aka ‘const struct __CFString *’)
错误中已经提示了我们须要如何做:用 __bridge 或者 __bridge_retained 来转型,其差别就是变革对象的所有权。
正因为Objective-C是ARC经管的对象,而Core Foundation不是ARC经管的对象,所以才要特地如许转换,这与id类型向void*转换是一个概念。也就是说,当这两种类型(有ARC经管,没有ARC经管)在转换时,须要告诉编译器如何处理惩罚对象的所有权。
上方的例子,应用 __bridge/__bridge_retained 后的代码如下:
__bridge12
NSString *string = [NSString stringWithFormat:...];CFStringRef cfString = (__bridge CFStringRef)string;
只是纯真地履行了类型转换,没有进行所有权的转移,也就是说,当string对象被开释的时辰,cfString也不克不及被应用了。
__bridge_retained1234
NSString *string = [NSString stringWithFormat:...];CFStringRef cfString = (__bridge_retained CFStringRef)string;...CFRelease(cfString); // 因为Core Foundation的对象不属于ARC的经管局限,所以须要本身release
应用 __bridge_retained 可以经由过程转换目标处(cfString)的 retain 处理惩罚,来使所有权转移。即使 string 变量被开释,cfString 还是可以运器具体的对象。只是有一点,因为Core Foundation的对象不属于ARC的经管局限,所以须要本身release。
实际上,Core Foundation 内部,为了实现Core Foundation对象类型与Objective-C对象类型的彼此转换,供给了下面的函数。
1234567
CFTypeRef CFBridgingRetain(id X) { return (__bridge_retained CFTypeRef)X;}id CFBridgingRelease(CFTypeRef X) { return (__bridge_transfer id)X;}
所以,可以用 CFBridgingRetain 调换 __bridge_retained 关键字:
1234
NSString *string = [NSString stringWithFormat:...];CFStringRef cfString = CFBridgingRetain(string);...CFRelease(cfString); // 因为Core Foundation不在ARC经管局限内,所以须要主动release。
所有权被转移的同时,被转换变量将落空对象的所有权。当Core Foundation对象类型向Objective-C对象类型转换的时辰,会经常用到 __bridge_transfer 关键字。
1234
CFStringRef cfString = CFStringCreate...();NSString *string = (__bridge_transfer NSString *)cfString;// CFRelease(cfString); 因为已经用 __bridge_transfer 转移了对象的所有权,所以不须要调用 release
同样,我们可以应用 CFBridgingRelease() 来庖代 __bridge_transfer 关键字。
12
CFStringRef cfString = CFStringCreate...();NSString *string = CFBridgingRelease(cfString);
总结
由上方的进修我们懂得到 ARC 中类型转换的用法,那么我们实际应用中遵守如何的原则或者办法来区分应用呢,下面我总结了几点关键要素。
- 明白被转换类型是否是 ARC 经管的对象
- Core Foundation 对象类型不在 ARC 经管局限内
- Cocoa Framework::Foundation 对象类型(即一般应用到的Objectie-C对象类型)在 ARC 的经管局限内
- 若是不在 ARC 经管局限内的对象,那么要清楚 release 的义务应当是谁
- 各类对象的生命周期是如何的Core Foundation 对象不属于ARC的管辖范围
- Core Foundation 对象不属于ARC的管辖范围
- Core Foundation 对象不属于ARC的管辖范围(转)
- ARC 和 非ARC 下 oc对象和core Foundation对象的转换
- 强制类型转化 转换是否成功不属于编译器的管辖范围,不合适的类型会让你得到运行时异常
- 当Core Foundation遇上ARC
- ARC between Foundation and Core Foundation
- Core Foundation对象的内存管理原则
- Core Foundation 对象的内存管理
- OC对象与Core Foundation对象的转换
- core foundation framework对象和foundation framework对象的相互转换 ---Toll-Free Bridging
- Core Foundation(C对象)与 Foundation(OC对象)之间的转换 理解
- Core Foundation(C对象)与 Foundation(OC对象)之间的转换 理解
- Foundation对象与Core Foundation对象间的转换:Toll-Free Birdge
- Core Foundation(C对象)与 Foundation(OC对象)之间的转换 理解
- python类型属于对象,不属于变量
- Objective-C对象和Core Foundation 对象
- Objective-C对象与Core Foundation对象
- Objective-C对象与Core Foundation对象
- linux alias方法临时失效的几种方法
- android action bar progress
- 免安装版tomcat的配置
- BBS Party
- [Unity3D]Unity3D游戏开发之使用UniSky呼风唤雨
- Core Foundation 对象不属于ARC的管辖范围
- linux+svn+google
- 高效开发 Android App 的 10 个建议
- 很早以前翻译的一篇文章,今天用到,又温习了一下,从博客转过来和大家分享。
- 在O(1)时间删除链表结点
- Android中的消息机制
- 找两个链表的第一个公共结点
- 解决Android SDK Manager更新、下载速度慢
- 递归