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,因此摆脱函数作用域对它的生命周期的影响。