Object-C 指针 和 C 指针的相互转换 与ARC 并验证__bridge关键字的作用
引用计数器
1.引用计数器,是伴随对象的产生而产生的。 当我们执行下面语句的时候,它就产生了一个对象,并且默认该对象的引用计数器为1:
id obj = [[NSObject alloc] init];
NSLog(@"obj retainCount=%lx", [obj retainCount]);
输出结果:
2014-07-29 18:32:59.346 Test_ARC_bridge[1127:303] obj retainCount=1
2.当我们在上面的代码加上另外一些代码时,如下(在ARC无效的情况下运行): id obj = [[NSObject alloc] init]; void *p =obj; [(id)p retain]; NSLog(@"p retainCount=%lx", [(id)p retainCount]); NSLog(@"obj retainCount=%lx", [obj retainCount]);
输出结果:
2014-07-29 18:26:49.324 Test_ARC_bridge[1100:303] p retainCount=2 2014-07-29 18:26:49.327 Test_ARC_bridge[1100:303] obj retainCount=2
分析上面代码:
void *p =obj; [(id)p retain];//retainCount+1这两句,相当与将p指针指向了obj对象,然后再将它的引用计数器+1,也就是等于2. 所以,(id)p和 obj他们指向的是同一个对象,固他们的引用计数器值是一样的。
__bridge、__birdge_retained与__bridge_transfer
1.当我们在ARC有效的情况下运行下面代码:
id obj = [[NSObject alloc] init]; void *p =obj;你会发现在,ARC有效的情况下,编译器不允许你隐式的将Object-C 指针转换成C指针,即有如下错误提示:
2.__bridge
查阅相关文档,我们可以用__bridge 关键字来解决这一问题,修改代码如下:
id obj = [[NSObject alloc] init]; void *p =(__bridge void *)obj; NSLog(@"obj retainCount=%x", _objc_rootRetainCount(obj));编译通过,输出结果:
2014-07-29 19:07:16.807 Test_ARC_bridge[1296:303] obj retainCount=1 //即P指针指向的该实体仍然是有效的注意:在使用ARC的时候,编译器不在允许我们明确调用retainCount函数了,使用会报错滴!(因为,ARC模式就是不需要你关心引用计数)
3.__bridge_retained 修改代码,使用__bridge_retained关键字代替__bridge关键字:
id obj = [[NSObject alloc] init]; void *p =(__bridge_retained void *)obj; NSLog(@"obj retainCount=%x", _objc_rootRetainCount(obj));
输出结果:
2014-07-29 19:18:04.187 Test_ARC_bridge[1315:303] obj retainCount=2
结合2和3两点,我们知道__bridge 与__bridge_retained的区别是,对象又有权的不同。即__bridge关键字,不对对象的引用计数器进行任何处理,而__bridge_retained 关键字则会让对象的引用计数器+1。同理,我们也可以推断出__bridge_transfer关键字是否同样对对象的所有权做了某些处理呢?
4.__bridge_transfer
修改代码,验证__bridge_transfer关键字的作用:
id obj = [[NSObject alloc] init]; void *p =(__bridge_retained void *)obj; NSLog(@"obj retainCount=%x", _objc_rootRetainCount(obj)); id objOther= (__bridge_transfer id)p; NSLog(@"objOther retainCount=%x", _objc_rootRetainCount(objOther));
输出结果:
2014-07-29 20:20:55.984 Test_ARC_bridge[1723:303] obj retainCount=2 2014-07-29 20:20:55.987 Test_ARC_bridge[1723:303] objOther retainCount=2
结果很让人意外啊:为什么还是2?
以上代码和结论只提供参考,个人水平有限,不一定准确。在此也是为了做个笔记,方便以后翻阅时能解决该疑惑! ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
参考其他文章引用过来的结论:
对象所有权策略是基于引用计数实现的
对象所有权的策略是通过引用计数——通常叫做retain count实现的。每一个对象有一个retaincount变量。
1.创建对象后,它的retaincount是1
2. retain之后,retain count +1
3.release之后 retain count -1
4.autorelease之后,在自动释放池最后-1
5.对象的retain count减少到0的时候,对象被销毁。
【重要】
不要显式调用对象的retainCount,结果往往具有误导性,作为开发者可能不了解框架式如何对对象retain的。在调试内存管理中,你应该只关注确保你的代码遵循所有权规则。
个人初步结论:
1. __bridge_retained 告诉ARC 一旦__bridge_retained转换完成,ARC就不用在负责释放该对象了,使用者需要手动释放,即使用者拥有该对象的持有权。相当于:
id obj = [[NSObject alloc] init]; void *p = obj; [(id)p retain];//即当obj变量被释放(出了大括号作用于)时,p变量仍然持有对象的所有权
2. __bridge_transfer 告诉ARC 一旦__bridge_transfer转换完成,ARC要负责释放该对象!相当于:
// p 变量原先持有对象的所有权 id obj = (id)p; [obj retain]; [(id)p release];//此后,ARC负责对obj对象所有权的管理
参考文章: http://blog.csdn.net/weiwangchao_/article/details/7744972 Core Foundation 框架 (有详细的说明)
http://book.2cto.com/201305/23871.html _objc_rootRetainCount 函数
http://www.cocoachina.com/applenews/devnews/2013/1126/7418.html iOS内存管理策略和实践
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。