2

我们在 iPad 3 上发生内存不足崩溃,我们追踪到以下情况:

使用 CATiledLayer 并绘制内容(例如 PDF)的 UIView 具有带有自己的 drawRect 方法的子视图(例如,突出显示搜索结果)。这使得 Core Animation 消耗大量内存(在 VM Tracker 工具中超过 100 MB),并且很容易导致崩溃。虽然所有设备都存在此问题,但只有在 iPad 的 Retina 显示屏上,缓存大小才会变得过大。

这可以通过 Apple 的PhotoScroller示例重现:子类 UIView,取消注释 drawRect,并将实例添加到 TilingView。该应用程序将在 iPad 3 上崩溃。评论 drawRect 解决了内存使用问题。

现在,我们可以放下子视图并在最顶层的 UIView 中进行绘图。但是,使用子视图很方便(因为我们在 PDF 之上表示不同的、独立的层)。两个问题:

  1. 什么是好的解决方法?最好是允许我们继续使用多个视图的。
  2. 为什么会发生这种情况?我猜缓存机制正在加班,但如果了解它背后的技术细节会很棒。

谢谢!

编辑:

我想详细说明凯的回答。该问题确实与 CATiledLayer 无关,而是与实现 drawRect 的 UIViews 的使用有关。

在 PhotoScroller 的情况下,我创建了一个 UIView,它的图像大小 - 2000x2000 或更大,如果 drawRect 存在,它会创建一个巨大的后备存储。

在我们的应用程序中,覆盖视图是全屏的(在 iPad 3 上 =~11 MB),每页大约有 5 个。滚动时我们在内存中最多保留三页,这意味着超过 150 MB 的额外内存。不好玩。

所以解决的办法就是优化drawRect掉,或者少用这样的view。回到绘图板它是:-)

4

2 回答 2

2

To 2.:每当您drawRectUIView子类中实现并拥有该类的大量实例时,您的内存使用量就会急剧增加。原因是UIKit视图/子视图处理中的许多优化技巧(例如缩放或滚动时)不适用于此类对象,因为框架不知道您在做什么/您在绘制什么。所以 - 独立于视网膜或不 - 避免实现drawRect,特别是当有许多对象或多层子视图时。

To 1.:我没有完全理解您正在尝试的内容,但我实现了一个 PDF-Viewer,它还能够在 PDF 之上显示其他内容。我用普通的 UIView 层次结构、图像等完成了这一切,我担心这是你能得到的唯一可靠的工作

于 2012-04-30T14:36:40.063 回答
1

我的经验:

  1. 永远不要将子视图添加到由 CATiledLayer 支持的 UIView
  2. 永远不要将子图层添加到 CATiledLayer

不幸的是,这似乎是唯一实际的答案——Apple 的实现在许多不同的方面都出现了可怕的错误(不仅仅是性能——渲染本身开始出现视觉伪影错误,Apple 的一些渲染代码变得奇怪等等)。

在实践中,我总是这样做:

UIView : 视图 +-- UIView w/ CATiledLayer : tiledLayerView +-- UIview : subViewsView

...并安全地将视图和子视图添加到“subViewsView”。工作正常。

于 2012-04-30T15:28:08.500 回答