ARC 之内存转换
技术博客http://www.cnblogs.com/ChenYilong/
新浪微博http://weibo.com/luohanchenyilong
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
ARC 之内存转换
技术博客http://www.cnblogs.com/ChenYilong/新浪微博http://weibo.com/luohanchenyilong
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_cf3d3e5c2bf803657156801886c5d7dc.png)
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_0b35eafe230b6f34f09569e5ff37bb7f.png)
Foundation对象&CoreFoundation对象
• 在iOS世界,主要有两种对象: - Objective-C 对象- Core Foundation 对象
• Core Foundation对象主要是有C语言实现的Core Foundation Framework 的对象,其中也有对象引用计数的概念,只是不是 Cocoa Framework的 retain/release,而是自身的CFRetain/ CFRelease 接口
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
• 在iOS世界,主要有两种对象: - Objective-C 对象- Core Foundation 对象
• Core Foundation对象主要是有C语言实现的Core Foundation Framework 的对象,其中也有对象引用计数的概念,只是不是 Cocoa Framework的 retain/release,而是自身的CFRetain/ CFRelease 接口
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
项目的ARC&MRC之间的转换
非ARC代码
ARC代码
id obj = [[NSObject alloc] init];!void *p = (__bridge void *)(obj);! obj = (__bridge id)(p);!
• 使用 __bridge 关键字可以实现id类型与void*类型 的相互转换
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
• 使用 __bridge 关键字可以实现id类型与void*类型 的相互转换
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
__bridge_retain
• __bridge_retain关键字表示类型被转换时,其对象
的所有权也将被变换后变量所持有• MRC代码如下:
id obj = [[NSObject alloc] init];
void *p = obj; [(id)p retain];
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
的所有权也将被变换后变量所持有• MRC代码如下:
id obj = [[NSObject alloc] init];
void *p = obj; [(id)p retain];
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
__bridge_retain测试程序
void *p = 0;
{
Person *obj = [[Person alloc] init];obj.name = @"liufan";
p = (__bridge void *)obj;
}
Person *tmp = (__bridge Person *)p;
NSLog(@"class=%@ %p %@", [(__bridge Person *)p class], p,tmp.name);
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
Person *obj = [[Person alloc] init];obj.name = @"liufan";
p = (__bridge void *)obj;
}
Person *tmp = (__bridge Person *)p;
NSLog(@"class=%@ %p %@", [(__bridge Person *)p class], p,tmp.name);
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
__bridge_transfer
• 当想把本来拥有对象所有权的变量,在类型转换 后,让其释放原先所有权的时候,需要使用__bridge_transfer 关键字
• MRC代码如下
id obj = (id)p; [obj retain]; [(id)p release];
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
• 当想把本来拥有对象所有权的变量,在类型转换 后,让其释放原先所有权的时候,需要使用__bridge_transfer 关键字
• MRC代码如下
id obj = (id)p; [obj retain]; [(id)p release];
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
小结
• __bridge_retained 是编译器替我们做了retain操作
• __bridge_transfer 是编译器替我们做了release操作
• __bridge 只是单纯地执行了类型转换,没有进行所有权的转移
• 注意:如果转换的是CFArrayRef,仍然需要手动释放内存
• 辅助解决方法:CMD+SHIFT+B
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
• __bridge_retained 是编译器替我们做了retain操作
• __bridge_transfer 是编译器替我们做了release操作
• __bridge 只是单纯地执行了类型转换,没有进行所有权的转移
• 注意:如果转换的是CFArrayRef,仍然需要手动释放内存
• 辅助解决方法:CMD+SHIFT+B
![](http://postachio-images.s3-website-us-east-1.amazonaws.com/96083b7bb56878d8f4821117b754ca3a/3adb9d62d2b6ed8b52b48a29a36fcdad/w600_897b223fe1bf63457e55de6d396ff5bb.png)
© chenyilong. Powered by Postach.io