启用CATiledLayer的UIView与drawRect定义的子视图由于异常内存使用而崩溃

时间:2012-04-30 13:18:38

标签: ios ipad uiview catiledlayer

我们在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. 为什么会这样呢?我想缓存机制正在加班,但理解它背后的技术细节会很棒。
  3. 谢谢!

    修改

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

    在PhotoScroller的情况下,我创建了一个UIView,其大小与图像相同 - 2000x2000及更高,如果存在drawRect,则会创建一个巨大的后备存储。

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

    因此,解决方案是优化drawRect,或使用更少的此类视图。回到绘图板是: - )

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

我的经历:

  1. 永远不要将子视图添加到由CATiledLayer支持的UIView
  2. 永远不要将子图层添加到CATiledLayer
  3. 不幸的是,这似乎是唯一可行的答案 - Apple的实现在许多不同方面都出现了可怕的错误(不仅仅是性能 - 渲染本身开始出现视觉伪像错误,Apple的一些渲染代码变得奇怪等等)。 / p>

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

    UIView:查看  + - UIView w / CATiledLayer:tiledLayerView  + - UIview:subViewsView

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