ARC下,初始化对象,如果不是alloc/new/copy/mutablecopy的方法,系统都会对对象进行处理,加入自动释放池,延迟释放时机。
新建一个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;
}
结果打印自动释放池内容,可以看到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等方法中的结果却是,自动释放池中不存在该对象,按道理如果加入自动释放池,是不可能马上释放的。唯一的解释是为加入自动释放池。此处保留疑问。
NSMutableArray *arr01 = [NSMutableArray array];
NSLog(@"%p", arr01);
_objc_autoreleasePoolPrint();
而对比两种项目,不同之处在于一个运行与Runloop中,一个没有。于是将command的代码改动,让对象的初始化发生在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;
}
运行发现,对象竟然不在自动释放池中。
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
三个方法的处理并不只是简单的放到自动释放池那么简单
网友评论