您的位置:首页 > 其它

ARC有效时,id和void*的显式转换

2015-07-17 17:09 253 查看
在ARC有效的情况下编译源代码,必须遵守一定的规则,其中之一就是“id”和“void *”需要显式转换。

在ARC无效时,像下面的代码这样进行id变量和void*变量进行强制转换是没有问题的:

@autoreleasepool {

id obj0 = [[NSObject alloc] init];

void* ptr = obj0;

id obj1 = ptr;

NSLog(@"obj retain count:%zi", [obj1 retainCount]);

[obj1 release];

//_objc_autoreleasePoolPrint();
}


但是这部分代码在ARC有效时会引起编译错误:



ARC有效的情况下需要遵循的另一条规则是:不能使用retain/release/retainCount/autorelease。

id类型或者对象型变量赋值给void *或者逆向赋值时(id类型和void*类型相互转换)需要进行显式的转换。如果只是单纯的赋值,可以使用“__bridge”进行显示转换。则上面的代码可以这项修改:

@autoreleasepool {

id obj0 = [[NSObject alloc] init];

void* ptr = (__bridge void*)obj0;

id obj1 = (__bridge id)ptr;

//_objc_autoreleasePoolPrint();
}


但是转换为void *的__bridge转换安全性比较低,如果管理时不注意赋值对象的所有者,很可能会因悬垂指针而导致程序崩溃。

为了补充__bridge转换的不足,还有另外两种转换,分别是“__bridge_retained”转换和“__bridge_transfer”转换。修改后的代码如下(__bridge_retained转换):

id obj0 = [[NSObject alloc] init];

void* ptr = (__bridge_retained void*)obj0;


__bridge_retained转换可使要转换赋值的变量也持有所赋值的对象,在ARC无效时能达到同样效果的代码如下:

id obj0 = [[NSObject alloc] init];

void* ptr = obj0;
[(id)ptr retain];

NSLog(@"obj retain count:%zi", [obj0 retainCount]); //obj retain count:2


下面说下__bridge_transfer转换,__bridge_transfer转换提供与__bridge_retained转换相反的操作,被转换的变量所持有的对象在该变量被赋值给转换目标后随之释放。__bridge_transfer转换代码如下:

id obj0 = [[NSObject alloc] init];

void* ptr = (__bridge_retained void *)obj0;

id obj1 = (__bridge_transfer id)ptr;


在ARC无效时与__bridge_transfer转换有同样效果的代码如下:

id obj0 = [[NSObject alloc] init];

void* ptr = obj0;

//等同__bridge_transfer
id obj1 = ptr;
[obj1 retain];
[(id)ptr release];

NSLog(@"obj retain count:%zi", [obj0 retainCount]); //obj retain count:1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: