1.__autoreleasing 是什么?
__autoreleasing 是oc中的一個(gè)與內(nèi)存管理相關(guān)的變量修飾符
2.__autoreleasing 能做什么忍些?
用__autoreleasing修飾的變量會(huì)自動(dòng)被添加至自動(dòng)緩存池(@autoreleasepool)
__autoreleasing修飾的變量的生命周期不再受當(dāng)前函數(shù)作用域影響檀头,轉(zhuǎn)而被自動(dòng)緩存池影響轰异,因此用__autoreleasing修飾變量可延長(zhǎng)變量的生命周期
@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);
}
控制臺(tái)輸出:
2020-03-18 20:33:29. [20030:716861] --1---(null)--(null)
2020-03-18 20:33:51. [20030:716861] --2---<NSObject: 0x600003d28390>--<NSObject: 0x600003d283a0>
2020-03-18 20:33:51. [20030:716861] --3---<NSObject: 0x600003d28390>--(null)
3.__autoreleasing 怎么做到的?
添加至自動(dòng)緩存池的變量會(huì)在緩存池結(jié)束的時(shí)候收到一次 release暑始,但是怎么做到擺脫當(dāng)前函數(shù)作用域影響的搭独?
- (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添加至自動(dòng)緩存池
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修飾后被加入至自動(dòng)緩存池,并且在函數(shù)結(jié)束時(shí)不會(huì)再調(diào)用objc_storeStrong廊镜,因此擺脫函數(shù)作用域?qū)λ纳芷诘挠绊憽?/p>