【问题标题】:Automatic Reference Counting and the UINavigationController自动引用计数和 UINavigationController
【发布时间】:2011-11-10 08:14:50
【问题描述】:

UINavigationController 与 ARC(自动引用计数)结合使用时遇到了一个非常奇怪的问题。 我有一个带有 UIViewController 的 iPad 应用程序,其中包含一个带有一些子视图的视图。 它的视图中有一个 UIScrollView(至少有 5 个子视图)和 2 个简单视图,一个黑条和一个白条。

每当我在 UINavigationController 堆栈(假设是 WebView)上推送某些内容时,当我收到内存警告时,UINavigationController 会在其堆栈上的所有当前和以前的 UIViewController 上调用 ViewDidLoad。

现在问题来了,当我从堆栈中弹出 WebView 并返回带有滚动视图的 UIViewController 时,它就消失了! 完全没电了。

我怀疑 -didReceiveMemoryWarning 方法在启用 ARC 后会在后台释放一些东西。如何强制 ARC 保持对这个特定的 ViewController 的控制?

有人可以帮我解决这个问题吗?因为此刻真的很烦我。

非常感谢!

-B

【问题讨论】:

  • 你是如何创建滚动视图的内容的?当您加载诸如 Web 视图之类的内容时,它们被删除是完全正常的,并且根据它们的创建方式,当您返回视图时,它们可能不会自动重新创建。这与 ARC 没有任何关系,它只是内存管理在 iOS 上的工作方式(如果发生内存不足警告并且您没有释放一些内存,您的应用程序将会崩溃)。您可以使用 iOS 模拟器中的“硬件 -> 模拟内存警告”对其进行测试。

标签: objective-c ios uinavigationcontroller automatic-ref-counting


【解决方案1】:

看起来您在 Web 视图中加载了非常重的内容,导致内存警告(或者您正在执行导致内存不足的其他事情)。 UINavigationController 接收-didReceiveMemoryWarning 并将其转发给所有卸载视图的视图控制器(-> viewDidUnload告诉你释放你不想留在内存中的东西。ARC 没有涵盖这一点,所以你必须消除所有与视图相关)。 当您返回时,会调用 loadViewviewDidLoad。您可能不会完全恢复您的视图 - 尤其是滚动视图 - 以匹配它们在内存警告之前所处的状态。
请记住,在 iOS 5 中,内存警告的发生频率低于以前的 iOS 版本(操作系统会尝试为您释放尽可能多的内存),但是当您收到内存警告时,这是您保持活力的最后机会。

【讨论】:

  • 内存密集型的东西发生在滚动视图中,它主要加载了 5 个包含相当大背景图像的子视图,以获得出色的视觉内容。 iPad 2 完美地解决了这个问题,这个错误只发生在 iPad 1 上。所以我会在每次弹回时恢复滚动视图,这应该在我认为的 viewDidLoad 方法中完成?
  • 我已经做了上面提到的事情,它似乎工作。非常感谢! :D
  • 大背景图片可能很危险..(尤其是 JPG 图片)。当您想要缩放时,您可以使用 CATiledLayer 延迟加载不同的缩放级别。并且您的最顶层滚动视图中的活动 CATiledLayer / UIImageView 对象不应超过 2 个 - 也许您应该考虑重用视图(如 UITableView 对单元格所做的那样)以节省内存。
  • WWDC 2010 上有关高级滚动视图技术的视频涵盖了两者:)
  • 它们是 PNG 文件,我没有缩放,所以 Tiled 的东西对于我的情况来说已经过时了。但是我对这个错误还有另一个问题:低内存警告的最佳做法是什么?删除所有子视图并在 didReceiveMemoryWarning 中将它们设置为 nil,然后在 viewDidUnload 中将它们设置为 nil,或者.. 其他什么?
猜你喜欢
  • 2012-03-21
  • 2012-03-13
  • 1970-01-01
  • 2010-11-01
  • 2017-02-17
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2010-11-06
相关资源
最近更新 更多