我最近加入了一个iPad项目。在查看代码库时,我遇到了一些不寻常的事情,其中之一就是这个(我已经对此进行了元编码):
while (something.isAlwaysTrue) {
// Wait for something to happen. i.e. Get data from an internet connection.
// Respond to something.
}
在我开始对应用程序进行内存分析之前,我没有发现任何问题,并发现这些循环是内存大量泄漏。原因是因为它们永远不会结束,所以在它们内部创建的任何autorelease
实例都不会被释放,因为该方法永远不会结束,自动释放池永远不会有机会释放。
在与编写代码的开发人员讨论之后,我提出了以下技术:
-(void) queueTask {
// Using GCD or perform with delay, call the process method.
}
-(void) process {
// Wait and/or do stuff.
[self queueTask];
}
基本思想是通过使用方法对GCD或runloop进行排队,它为自动释放池提供了执行和清理autorelease
实例的机会。这似乎工作正常。
我的问题是 - 这是处理这些循环的最佳方法吗?或者有更好的方法吗?
答案 0 :(得分:8)
两点;
尽量减少堆增长
无论如何,这是如何最大限度地减少内存增长:
while (something.isAlwaysTrue) {
NSAutoreleasePool * pool = [NSAutoreleasePool new];
// Wait for something to happen. i.e. Get data from an internet connection.
// Respond to something.
[pool release], pool = 0;
}
或者如果你更喜欢咩咩(sic)边缘:
while (something.isAlwaysTrue) {
@autoreleasepool{
// Wait for something to happen. i.e. Get data from an internet connection.
// Respond to something.
}
}
autorelease pool就像线程本地堆栈一样运行。当您推送池时,自动释放的对象将添加到当前线程的顶层池中。当您弹出池时,池会为每个自动释放发送一条release
消息。
使用GCD代替自动释放池是奇怪的;类似于使用NSArray
单个字符NSString
,您应该只使用一个NSString
。
Mutithreaded Program Flow
无限循环是一个非常可疑的程序。它建议你可能正在尝试重新发明运行循环。主运行循环当然是常见的。具有永不结束的运行循环2)的辅助线程1)是不寻常的。
您应该重新考虑该计划的流程。通常情况下,你采取行动,而不是屏住呼吸,轮询直到完成。你可能试图在你提出的计划中摆脱这种情况 - 但我没有足够的细节。