__autoreleasing 如何做到延迟释放的?

1.__autoreleasing 是什么?

__autoreleasing 是oc中的一个与内存管理相关的变量修饰符

2.__autoreleasing 能做什么?

用__autoreleasing修饰的变量会自动被添加至自动缓存池(@autoreleasepool)

__autoreleasing修饰的变量的生命周期不再受当前函数作用域影响,转而被自动缓存池影响,因此用__autoreleasing修饰变量可延长变量的生命周期

@property(nonatomic,weak)NSObject *weakObj1;
@property(nonatomic,weak)NSObject *weakObj2;


- (void)test {
     NSLog(@"--1---%@--%@",self.weakObj1,self.weakObj2);
     [self test2];
     NSLog(@"--3---%@--%@",self.weakObj1,self.weakObj2);
 }


- (void)test2 {
     __autoreleasing NSObject *obj1 = [NSObject new];
     NSObject *obj2 = [NSObject new];
     self.weakObj1 = obj1;
     self.weakObj2 = obj2;
     NSLog(@"--2---%@--%@",self.weakObj1,self.weakObj2);
 }

控制台输出:

2020-03-18 20:33:29. [20030:716861] --1---(null)--(null)
2020-03-18 20:33:51. [20030:716861] --2-----
2020-03-18 20:33:51. [20030:716861] --3-----(null)

3.__autoreleasing 怎么做到的?

添加至自动缓存池的变量会在缓存池结束的时候收到一次 release,但是怎么做到摆脱当前函数作用域影响的?

- (void)test2 {
    
    __autoreleasing NSObject *obj1 = [NSObject new];

    NSObject *obj2 = [NSObject new];  

}

编译成汇编如下:

Giftfff`-[Oobj test2]:
    0x103e61140 <+0>:   pushq  %rbp
    0x103e61141 <+1>:   movq   %rsp, %rbp
    0x103e61144 <+4>:   subq   $0x30, %rsp
    0x103e61148 <+8>:   movq   %rdi, -0x8(%rbp)
    0x103e6114c <+12>:  movq   %rsi, -0x10(%rbp)
    0x103e61150 <+16>:  movq   0x245a59(%rip), %rsi      ; (void *)0x00007fff89e066c0: NSObject
    0x103e61157 <+23>:  movq   0x245162(%rip), %rdi      ; "new"
    0x103e6115e <+30>:  movq   %rdi, -0x28(%rbp)
    0x103e61162 <+34>:  movq   %rsi, %rdi
    0x103e61165 <+37>:  movq   -0x28(%rbp), %rsi
    0x103e61169 <+41>:  callq  *0x22ac21(%rip)           ; (void *)0x00007fff513f7780: objc_msgSend
    0x103e6116f <+47>:  movq   %rax, %rdi
    0x103e61172 <+50>:  callq  0x10405861a               ; symbol stub for: objc_autorelease
    0x103e61177 <+55>:  movq   %rax, -0x18(%rbp)
->  0x103e6117b <+59>:  movq   0x245a2e(%rip), %rax      ; (void *)0x00007fff89e066c0: NSObject
    0x103e61182 <+66>:  movq   0x245137(%rip), %rsi      ; "new"
    0x103e61189 <+73>:  movq   %rax, %rdi
    0x103e6118c <+76>:  callq  *0x22abfe(%rip)           ; (void *)0x00007fff513f7780: objc_msgSend
    0x103e61192 <+82>:  xorl   %ecx, %ecx
    0x103e61194 <+84>:  movl   %ecx, %esi
    0x103e61196 <+86>:  movq   %rax, -0x20(%rbp)
    0x103e6119a <+90>:  leaq   -0x20(%rbp), %rax
    0x103e6119e <+94>:  movq   %rax, %rdi
    0x103e611a1 <+97>:  callq  0x104058680               ; symbol stub for: objc_storeStrong
    0x103e611a6 <+102>: addq   $0x30, %rsp
    0x103e611aa <+106>: popq   %rbp
    0x103e611ab <+107>: retq   

将汇编再翻译成伪代码:

- (void)test2{
    
   // __autoreleasing NSObject *obj1 = [NSObject new]; 等同于:
    id obj1 = objc_msgSend(NSObject, @selector(new));
    objc_autorelease(obj1);
    
   // NSObject *obj2 = [NSObject new]; 等同于:
    id obj2 = objc_msgSend(NSObject, @selector(new));
    defer {
       objc_storeStrong(&obj2,nil)
    }   
}

其中 objc_autorelease(obj1) 即是将obj1添加至自动缓存池

objc_storeStrong 则如下:

void objc_storeStrong(id *location, id obj)
{
    id prev = *location;
    if (obj == prev) {
        return;
    }
    objc_retain(obj);
    *location = obj;
    objc_release(prev);
}

obj1 在被__autoreleasing修饰后被加入至自动缓存池,并且在函数结束时不会再调用objc_storeStrong,因此摆脱函数作用域对它的生命周期的影响。

你可能感兴趣的:(__autoreleasing 如何做到延迟释放的?)