ARC中__bridge_transfer与CFBridgingRelease结果不一致问题咨询
为什么ARC下CFBridgingRelease和__bridge_transfer的结果不一致?
兄弟,我太懂你这困惑了——按道理ARC环境里CFBridgingRelease和__bridge_transfer应该是完全等价的,但你的代码测出来的 retain count 却不一样,对吧?咱们来一步步拆解问题出在哪。
先把你的代码贴出来方便分析:
int main(int argc, const char * argv[]) { @autoreleasepool { CFMutableArrayRef cfObject = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); printf("retain count = %ld\n", CFGetRetainCount(cfObject)); //id obj = (__bridge_transfer id)(cfObject); id obj = CFBridgingRelease(cfObject); printf("retain count after the cast = %ld\n", CFGetRetainCount(cfObject)); NSLog(@"class=%@", obj); } }
核心问题:你在操作一个已经失效的指针!
首先得明确一个关键事实:CFBridgingRelease本质上就是__bridge_transfer的宏定义——你去看系统头文件就能发现,它的定义就是:
#define CFBridgingRelease(X) ((__bridge_transfer id)(X))
所以两者从功能上是100%等价的,不存在任何逻辑差异。
那你看到的不同结果是怎么来的?问题出在这句代码:
printf("retain count after the cast = %ld\n", CFGetRetainCount(cfObject));
当你调用CFBridgingRelease(cfObject)或者__bridge_transfer时,已经把cfObject的所有权转移给了OC对象obj,此时ARC完全有权立即释放原CF对象,或者让cfObject变成野指针。这时候再去调用CFGetRetainCount(cfObject)属于未定义行为,返回的数值完全不可信,可能因为编译器优化、ARC的自动操作而随机变化,根本不能用来判断两者的差异。
正确的测试姿势
转移所有权后,别再碰原来的CF指针了,把注意力放在OC对象obj上。比如改成这样测试:
int main(int argc, const char * argv[]) { @autoreleasepool { CFMutableArrayRef cfObject = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); printf("CF retain count before transfer = %ld\n", CFGetRetainCount(cfObject)); // 这里应该是1 id obj = CFBridgingRelease(cfObject); // 改用OC对象的retainCount(虽然ARC下这个值也仅供参考,但至少不会操作野指针) printf("OC retain count after transfer = %ld\n", [obj retainCount]); NSLog(@"class=%@", obj); } }
总结
CFBridgingRelease和__bridge_transfer没有任何功能差异,你看到的不同结果只是因为操作了已经失效的CF指针导致的随机现象。在ARC下,一旦完成所有权转移,就应该彻底抛弃原CF指针,只使用转换后的OC对象。
内容的提问来源于stack exchange,提问作者EricXuan
相关产品推荐
相关产品推荐

