我有兴趣了解更多关于如何在使用 ARC 的紧密循环下最好地处理内存管理的信息。特别是,我有一个我正在编写的应用程序,它有一个while
循环运行了很长时间,我注意到尽管在 ARC 中实现了(我相信是)最佳实践,但堆仍然存在无限成长。
为了说明我遇到的问题,我首先将以下测试设置为故意失败:
while (true) {
NSMutableArray *array = [NSMutableArray arrayWithObject:@"Foo"];
[array addObject:@"bar"]; // do something with it to prevent compiler optimisations from skipping over it entirely
}
运行此代码并使用分配工具进行分析表明内存使用量无休止地增加。但是,将其包装@autoreleasepool
如下,可以立即解决问题并保持内存使用良好且低:
while (true) {
@autoreleasepool {
NSMutableArray *array = [NSMutableArray arrayWithObject:@"Foo"];
[array addObject:@"bar"];
}
}
完美的!这一切似乎都运行良好——甚至对于使用[[... alloc] init]
. 一切正常,直到我开始涉及任何UIKit
课程。
例如,让我们创建一个UIButton
并看看会发生什么:
while (true) {
@autoreleasepool {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectZero;
}
}
现在,内存使用量无限增加——实际上,似乎@autoreleasepool
没有任何效果。
所以问题是为什么@autoreleasepool
对 和 保持内存正常工作NSMutableArray
,但是当应用于 a 时UIButton
,堆继续增长?
UIKit
最重要的是,当在这样的无限循环中使用类时,如何防止堆无限扩展,这告诉我们关于 ARCwhile(true)
或while(keepRunningForALongTime)
样式循环的最佳实践是什么?
我对此的直觉是(我可能完全错了)可能是关于如何while (true)
保持运行循环不循环,这将UIKit
实例保存在内存中而不是释放它们......但显然我错过了一些东西我对ARC的理解!
(并且为了消除一个明显的原因,NSZombiedEnabled
没有启用。)