如果你使用过MRR,autorelease这个关键字应该是太熟悉了,每次在我们生成一个新的对象返回时,都需要向这个对象发送autorelease消息,目的是为了延时释放创建的对象。那到底是在什么时候,这个对象会被释放呢?有什么方法可以更快的释放一个autorelease对象呢?
咱们先来看一个现象:
@property (weak, nonatomic) NSString *weakString; - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. NSString *hello = [[NSString alloc] initWithCString:"it will be released at the end of current runloop" encoding:NSUTF8StringEncoding]; self.weakString = hello;
NSLog(@"%@ - %@", self.weakString, NSStringFromSelector(_cmd));
} - (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"%@ - %@", self.weakString, NSStringFromSelector(_cmd));
} - (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"%@ - %@", self.weakString, NSStringFromSelector(_cmd)); dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"-2--%@ - %@", self.weakString, NSStringFromSelector(_cmd));
});
}
我们创建了一个viewDidLoad方法中创建了一个weak指针指向一个字符串,当代码执行到viewWillAppear:和viewDidAppear:时,我们依然可以打印出weak指针指向的字符串,当在viewDidAppear:中在下一个runloop中执行打印操作时,weak指针就指向nil了,why ?
编译器在ARC环境下可能会帮我们把这条语句self.weakString = hello改成类似这样:
self.weakString = [[hello retain] autorelease];
当向hello发送autorelease消息时,hello将会被加入到当前的autorelease pool中,当autorelease pool release时,它会像pool中hello发送release消息,然后hello就被真正释放了。
可是看看我们的示例代码,我们并没有autorelease pool啊,我们知道app启动时main函数里面有一个autorelease pool,难道是这个autorelease pool被释放了? 显然不可能,那可以肯定的说,系统隐式的帮我们创建了autorelease pool。
系统怎么知道我们要为我们创建autorelease pool的呢?
main函数启动后系统会创建一个main runloop,每个runloop系统都会分配一个autorelease pool,它将在app退出的时候释放app所占用的内存。当用户输入设备(如点击button、键盘按下)、网络链接(socket收到数据)、定期或时间延迟事件(NSTimer),还有异步回调(NSURLConnection的异步请求)等三类(sources、timers、observers)会将这个main runloop激活并产生一个autorelease pool,当runloop进入睡眠时,释放这个autorelease pool。
比如我们的demo里面,是一个cell点事件触发了一个页面切换,从点击cell点击激活runloop到新页面的viewDidAppear:结束后runloop进入休眠,这中间创建的autorelease pool就是那个把weakString释放的家伙。
参考资料:
1)http://www.cnblogs.com/whyandinside/p/3489951.html
2)https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html