2

Apple 文档中,它说:

AppKit 和 UIKit 框架处理自动释放池块中的每个事件循环迭代(例如鼠标按下事件或点击)。因此,您通常不必自己创建自动释放池块,甚至不必查看用于创建自动释放池的代码。

现在,这应该很明显,但无论如何我都会要求确认。

如果我正在开发最终将成为后台进程的内容(通过 Grand Central Dispatch),但为简单起见,我首先将其放在第一个加载视图的 viewDidLoad 中,这样我的视图实际上不会显示在屏幕上,直到所有(比如说)2 分钟的处理都完成了,然后在这两分钟内,所有默认的自动释放池都不会被释放,因为它还没有通过事件循环迭代,对吗?听到拒绝简直是疯了,但我陷入了这个日益严重的记忆问题,所以我会要求确认并希望有一个好消息。

如果是这样,我应该放置我自己的自动释放块。如果处理是通过 GCD 在后台进程中完成的,我仍然需要自动释放块,对吗?

4

2 回答 2

4

我会尽力给你一个完整的回答你的两个问题。

第一部分。首先要注意主线程中长时间运行的操作。例如,如果您的操作需要两分钟,则主线程将被阻塞,直到它完成。从用户的角度来看,应用程序将在两分钟内没有响应。无论如何,是的,在应用程序委托中有一个插入自动释放对象的池。当循环结束时,池内的对象会被释放,因为池会自动排空。如果你有内存问题,你可以看看Use Local Autorelease Pool Blocks to Reduce Peak Memory Footprint。如文档中所写,您应该将操作包装在自动释放块中。在块的末尾,临时对象被释放,这通常会导致它们的释放,从而减少程序的内存占用。

关于 GCD 问题,我会说不。处理 GCD 时不必创建自动释放池。通常,也写在你需要在 GCD 的块内创建一个 NSAutoreleasePool 吗?, GCD 自动管理每个队列的自动释放池。所以,如果你的对象很少,你不必担心,但如果你创建了很多,是的,创建一个自动释放池。后者还允许您减少内存占用。

因此,对于应用程序没有响应的整整两分钟,是在循环尚未结束的情况下,并且在这两分钟内池没有耗尽,对吗?

该应用程序没有响应,因为主线程(通过运行循环)按顺序执行任务。如果您阻止运行循环,应用程序会冻结,直到长时间运行的操作完成(我认为如果您超过特定时间段,应用程序会被 iOS 杀死)。为避免这种情况,您可以(如您所写)在不同的线程中执行长时间运行的操作。

使用线程的目的是使应用程序具有高响应性,但它​​可能会导致各种问题,如不一致的数据(竞争条件)或死锁

有关更多信息,我真的建议阅读NSRunLoop 的弹簧棒了解 NSRunLoopNSDefaultRunLoopMode vs NSRunLoopCommonModes

于 2012-08-31T16:30:25.003 回答
0

您不需要创建自己的自动释放块来管理自动释放对象的内存;有一个池,它自动管理的,自动释放的对象最终被释放。

因此,唯一的问题是“最终”这个神奇的词。在您的处理过程中,您的应用程序是否因为尚未释放的自动释放对象而使用过多内存(例如,系统将杀死它的内存量过多)?记住,他们被释放;问题是情况是否如此糟糕以至于您需要立即释放它们而无需等待自动释放池的耗尽,这肯定在您不采取任何行动的情况下发生。

只有 Instruments 能告诉你,所以不要猜测,不要过早优化;看看仪器揭示了什么。如果情况那么糟糕,那么当然,找到生成所有这些自动释放对象的循环并在其中放置一个自动释放块,以便每次通过循环时都会耗尽池。否则,真的没有必要。(另一方面,在 ARC 下,自动释放块增加的开销很小,因此过早优化也可能不会造成太大危害。)

于 2012-08-31T17:06:31.743 回答