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

在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

 

posted @ 2015-07-17 17:09  驴车手  阅读(555)  评论(0编辑  收藏  举报