ARC下,初始化對象,如果不是alloc/new/copy/mutablecopy的方法,系統(tǒng)都會對對象進行處理,加入自動釋放池,延遲釋放時機。
新建一個MacOS command line的項目
extern uintptr_t _objc_rootRetainCount(id obj);
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
NSMutableArray *arr01 = [NSMutableArray array];
NSLog(@"%p", arr01);
_objc_autoreleasePoolPrint();
return 0;
}
結(jié)果打印自動釋放池內(nèi)容,可以看到arr01是被添加到自動呢釋放池中。
2020-04-27 13:45:39.253262+0800 AutoReleaseCMD[2977:131172] 0x10045dc80
objc[2977]: ##############
objc[2977]: AUTORELEASE POOLS for thread 0x1000d2dc0
objc[2977]: 1 releases pending.
objc[2977]: [0x10080b000] ................ PAGE (hot) (cold)
objc[2977]: [0x10080b038] 0x10045dc80 __NSArrayM
objc[2977]: ##############
Program ended with exit code: 0
但是同樣的代碼,放到iOS項目viewDidLoad等方法中的結(jié)果卻是,自動釋放池中不存在該對象,按道理如果加入自動釋放池,是不可能馬上釋放的。唯一的解釋是為加入自動釋放池。此處保留疑問。
NSMutableArray *arr01 = [NSMutableArray array];
NSLog(@"%p", arr01);
_objc_autoreleasePoolPrint();
而對比兩種項目,不同之處在于一個運行與Runloop中,一個沒有。于是將command的代碼改動,讓對象的初始化發(fā)生在runloop中。
extern uintptr_t _objc_rootRetainCount(id obj);
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
NSLog(@"1");
[[NSRunLoop currentRunLoop] performBlock:^{
NSMutableArray *arr01 = [NSMutableArray array];
NSLog(@"%p", arr01);
_objc_autoreleasePoolPrint();
}];
[[NSRunLoop currentRunLoop] runUntilDate:[[NSDate date] dateByAddingTimeInterval:1000]];
NSLog(@"2");
return 0;
}
運行發(fā)現(xiàn),對象竟然不在自動釋放池中。
2020-04-27 13:53:16.209729+0800 AutoReleaseCMD[3005:134437] 1
2020-04-27 13:53:16.210792+0800 AutoReleaseCMD[3005:134437] 0x10042dfb0
objc[3005]: ##############
objc[3005]: AUTORELEASE POOLS for thread 0x1000d3dc0
objc[3005]: 2 releases pending.
objc[3005]: [0x100810000] ................ PAGE (hot) (cold)
objc[3005]: [0x100810038] 0x10042bf90 __NSSingleObjectArrayI
objc[3005]: [0x100810040] ################ POOL 0x100810040
objc[3005]: ##############
objc_autoreleaseReturnValue
objc_unsafeClaimAutoreleasedReturnValue
objc_retainAutoreleasedReturnValue
三個方法的處理并不只是簡單的放到自動釋放池那么簡單