参考sunnyxx的黑幕背后的Autorelease
在看sunnyxx大大的文章时,发现有个部分理解的不是很清楚,然后自己做了个补充,权当笔记以备后用
在没有手动干预Autorelease Pool的情况下,Autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop
__weak id refStr = nil;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *str = [NSString stringWithFormat:@"runloop test"];
refStr = str;
NSLog(@"%s=======%@",__func__,[NSRunLoop currentRunLoop]);//CFRunLoop 0x174178600 [0x1a9b45bb8]> current mode = UIInitializationRunLoopMode
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"str in %s: %@",__func__,refStr); //str in -[ViewController viewWillAppear:]: runloop test
NSLog(@"%s=======%@",__func__,[NSRunLoop currentRunLoop]); // <CFRunLoop 0x174178600 [0x1a9b45bb8]> current mode = UIInitializationRunLoopMode,
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(@"str in %s: %@",__func__,refStr); // str in -[ViewController viewDidAppear:]: (null)
NSLog(@"%s=======%@",__func__,[NSRunLoop currentRunLoop]);//CFRunLoop 0x174178600 [0x1a9b45bb8]> current mode = kCFRunLoopDefaultMode
}
输出结果中,在viewDidLoad
和viewWillAppear
中refStr
都是有值的,而viewDidAppear
中就已经释放掉了. 还可以看到在三个方法中 RunLoop 的内存地址都是相同的,但是在viewDidLoad
和viewWillAppear
中 RunLoop 的 mode 是 UIInitializationRunLoopMode
,而在viewDidAppear
中是kCFRunLoopDefaultMode
. 注意:
当 RunLoop 切换 mode 时,只能退出后再重新进入.
所以,在执行viewDidAppear
时,会把上一个 RunLoop 中的releapool对象释放掉.这也就是viewDidAppear
中输出为 null 的原因.
网友评论