以下情景均為 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 中及時釋放掉。