• 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
  • 相关阅读:
    kali linux安装vm
    视频学习_css基础学习
    w3c_html_study_note_5.26
    备份apt目录节省下载时间
    校园网小记
    [原创汉化]linux前端神器 WebStorm8 汉化
    虚拟机备份转移后,网络启动异常,提示“SIOCSIFADDR: No such device”的解决方案
    python开发之virtualenv与virtualenvwrapper讲解
    Nginx负载均衡概述
    centos7安装python3 以及tab补全功能
  • 原文地址:https://www.cnblogs.com/arthas/p/4655143.html
Copyright © 2020-2023  润新知