ARC:内存无法回收?

时间:2012-02-22 06:08:33

标签: objective-c ios ipad memory automatic-ref-counting

我正在使用iPad(仅限)应用程序,我偶然发现了一个奇怪的问题。在iPad 1上发出内存警告后应用程序终止,但在iPad 2上运行正常。 我使用ARC并以iOS 5为目标。我使用笔尖,我的大部分资产都是使用UIImageViews显示的。我还有几百个按钮和大量的手势识别器......我在ARC上重新观看了WWDC11视频(会话323和322),我似乎没有做任何特别的事情。

该应用程序是UIImage密集型的,我正在使用UIImage做很多动画。然而,我使用initWithContentsOfFile构造函数而不是imageNamed调用。我正试图阻止图像被系统缓存。

我也在使用GCD来安排声音效果和动画视图。我总是在主线程上这样做。

该应用程序使用UINavigationController,它的堆栈上永远不会有超过1个UIViewController。我可以确认这是真的,因为只在当前视图控制器上调用didReceiveMemoryWarning(我正在记录调用)。

我不明白的是,为什么Instruments在Allocations和VM Tracker工具中都报告了高数字(就好像视图控制器没有被取消分配)。当我从一个视图控制器导航到另一个视图控制器时,Allocations仪器会显示一个小的下降(这是我所期望的)但是当我做同样的事情时,VM Tracker Instrument显示Dirty Size没有下降。最终,该应用程序使用了太多内存并被终止(在iPad 1上)。当我在iPad 2上收到内存警告时,该应用程序不会被终止...

感觉好像我的图像,声音或视图没有被破坏而内存没有被回收......我的对象层次结构是非常基本的,不应该有任何类型的保留周期。我甚至没有简单的代表......

你有什么建议吗?我真的不想只为iPad 2或更新版本发布这个应用程序......这是一个适合孩子的应用程序,这将是一个很小的...我会更高兴地了解到我做错了什么,因为我真的想确保这个应用程序是最好的...

干杯, 尼克

2 个答案:

答案 0 :(得分:1)

有些方法可以说'优化'你的对象,当不需要某些东西时将它们的属性设置为nil - 所以当你不能再编写dealloc方法时,你可以做self.object = nil(当相关时)最终在非ARC世界中为“保留”(即strong)属性执行类似的操作:

- (void)setObject:(id)newObject
{
   [object release]; // send release message to current object
   object = newObject; // set reference to newObject
   [object retain]; // send retain message to newObject
}

现在在ARC中你没有/不能在你的代码中自己编写保留/释放,编译器会为你插入这些调用,这意味着在实践中,将属性设置为nil会在上面的例子:

[object release]; // send release message to current object
object = nil; // set reference to nil
[object retain]; // send retain message to nil (no effect)

此外,这只是冰山一角 - 您应该确保代码中有no retain cycles,这可能会导致对象泄漏而无法使用它们进行破坏。这意味着,当您应该使用strong属性时,可能存在使用weak对属性(即对象)的引用的位置。不同之处在于,强引用为retain ed,weak引用为assign,前者使其retainCount递增,后者导致属性赋值,如果手写则如下所示:

- (void)setObject:(id)newObject
{
   object = newObject;
}

答案 1 :(得分:1)

我不喜欢回答我自己的问题,但我认为它可能对未来的googlers有所帮助。我实现了自己的基于UIImage的动画,我不再使用animationImages属性。事实证明我的内存问题现在已经消失,因为我不再需要将所有图像存储在内存中,并且我需要使用计时器加载它们。

我实际上认为推出自定义动画是有益的,因为它允许回调和更强大的自定义选项。

一旦我对它感到满意并且我觉得它已经准备好分享了,我会在GitHub上发布课程。