美文网首页
ARC原理分析

ARC原理分析

作者: zziazm | 来源:发表于2020-04-27 15:41 被阅读0次

    https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-retainautorelease

    编译器会自动添加retain、release和autorelease,还有运行时的协助。

    可以通过以下方式将代码编译成中间语言:
    clang -S -fobjc-arc -emit-llvm main.m -o main.ll
    可以看到编译器是在什么地方做的操作。

    • __strong修饰符
      __strong是id类型和对象类型默认的修饰符。
    {    
       __strong  id obj = [[NSObject alloc] init];
    }
    

    编译成中间语言后:


    WeChat601fb47f7f90116f31cf7e35fe4ea621.png

    上面划线的模拟代码大概是这样的:

    {
     id obj = objc_msgSend(NSObject, @selector(alloc));
     objc_msgSend(obj, @selector(init));
     objc_storeStrong(&obj, null);
    }
    

    了解一下objc_storeStrong代码:

    void objc_storeStrong(id *object, id value) {
      id oldValue = *object;
      value = [value retain];
      *object = value;
      [oldValue release];
    }
    

    第一个参数是object的地址,这个函数相当于对对象object做了一次release操作。
    因此,__strong修饰的alloc出来的对象在出作用域时编译器会添加 release。

    再看一下下面的代码:

    {
        __strong  id obj1 = [[NSObject alloc] init];
        __strong  id obj2 = obj1;
    }
    

    编译器模拟代码:

    {
     id obj1 = objc_msgSend(NSObject, @selector(alloc));
     objc_msgSend(obj1, @selector(init));
     id obj2 = objc_retain(obj1);
     objc_storeStrong(&obj1, null);
     objc_storeStrong(&obj2, null);
    }
    

    可以看到,__strong修饰的对象直接赋值时编译器会添加retain。

    再看一下使用类方法构造的对象:

     __strong NSArray *arr = [NSArray array];
    

    编译器模拟代码:

     id arr = objc_msgSend(NSArray, @selector(array));
    objc_retainAutoreleasedReturnValue(arr);
    objc_storeStrong(&arr, null);
    

    使用类方法构造的对象和alloc init不同的地方在于多了一个objc_retainAutoreleasedReturnValue(arr).
    objc_retainAutoreleasedReturnValue这个函数是成对出现的,和它对应的是objc_autoreleaseReturnValueobjc_autoreleaseReturnValue是在类方法里出现的:

    + (NSArray *)array{
        return [[NSArray alloc] init];
    }
    

    编译器模拟代码:

     id obj = objc_msgSend(NSObject, @selector(alloc));
    objc_msgSend(obj, @selector(init));
    return objc_autoreleaseReturnValue(obj);
    

    objc_retainAutoreleasedReturnValue()
    objc_autoreleaseReturnValue ()这两个函数的作用是什么呢?
    objc_autorelease()函数会将对象注册到autorelesaepool中,objc_autoreleaseReturnValue和它不同,objc_autoreleaseReturnValue会检查使用该函数的方法或调用放的执行命令列表,如果方法或函数调用方紧接着调用了objc_retainAutoreleasedReturnValue,就不会把返回值注册到autorelesaepool中,这样就做了一个优化,可以不将对象注册到autorelesaepool,直接传递。

    • __weak修饰符
      __weak修饰的变量不会持有对象的引用计数,当对象释放是,会将爱那个边来那个置nil。
    NSObject *obj;
    __weak id obj1 = obj;
    

    编译器模拟代码里会有四个函数:

    @objc_initWeak()
    @objc_loadWeakRetained()
    @objc_release()
    @objc_destroyWeak() 
    

    objc_loadWeakRetained()函数会retain对象,这样可以保证在使用weak对象时对象不会被释放掉。
    -__autoreleasing
    __autoreleasing修饰的变量会注册到自动释放池里:

    __autoreleasing NSObject *obj = [NSArray array];
    

    编译器模拟代码:

     id obj = objc_msgSend(NSObject, @selector(alloc));
    objc_autorelease(obj);
    

    objc_autorelease()会将对象注册到自动释放池里。

    相关文章

      网友评论

          本文标题:ARC原理分析

          本文链接:https://www.haomeiwen.com/subject/zgtzsttx.html