以下情景均为 ARC 环境
情景 1:
for ( int i = 0; i < 10000000; i++) {
NSString *str = [[NSString alloc] initWithFormat:@"dang %d", i];
}
分析:str 的默认变量内存管理语义是 __strong,在每次循环之后,会自动 release 掉。
情景 2:
for ( int i = 0; i < 10000000; i++) {
NSString *str = [NSString stringWithFormat:@"dang %d", i];
}
分析:内存暴涨说明没有调用 objc_retainAutoreleasedReturnValue ,也就是说,stringWithFormat:返回的是一个 autorelease 对象。而此时 runloop 由于 for 循环没有结束一直处于醒着的状态,直到 for 循环结束才会倾倒自动释放池,在这过程中产生的大量的 autorelease 对象使得内存暴涨。
情景 3:
for ( int i = 0; i < 10000000; i++) {
@autoreleasepool {
NSString *str = [NSString stringWithFormat:@"dang %d", i];
}
}
分析:为了解决情景 2 中的问题,每次循环时创建一个自动释放池,临时对象可以及时 release 掉,就不会使得内存暴涨了。
总结:
什么时候使用自动释放池?
在一些博客中说的是在 loop 中 NSData 转为 UIImage 时,在一些技术群中也有不少人是这么回答的。其实这只是使用自动释放池的一种情况,归根结底是 在 loop 中通过非 alloc/new/copy/mutableCopy 方法创建对象 时使用,例如[NSMutableArray array];
、[UIImage imageWithData:data];
,这些方法创建的 autorelease 对象需要放在 pool 中及时释放掉。