CATiledLayer显示以前的图块

时间:2016-10-06 08:43:24

标签: ios swift catiledlayer

当CATiledLayer支持的视图无效时,前一个图块仍然“卡住”并且未正确无效。

这似乎发生在视图无效时(在主线程上),同时,磁贴渲染线程仍然在以前版本的磁贴上工作。不是缓存新版本的磁贴,而是缓存先前版本。

CATiledLayer支持的视图是UIScrollView的子视图,可以缩放。平铺的渲染可能很昂贵,并且可以使用渲染线程10ms。

实施例

演示此问题的示例代码:https://github.com/Q42/CATiledLayerBug

  1. 在CATiledLayer中,开始渲染所有红色图块(这将需要大约3秒钟才能完成)
  2. 每个渲染步骤大约需要10毫秒
  3. 在渲染期间(800毫秒后),使整个视图无效:tiledView.setNeedsDisplay()
  4. 开始渲染所有灰色瓷砖(这又需要大约3秒钟)
  5. 两块瓷砖(随机?)保持红色,而不是变灰。
  6. 请在此处查看update功能:https://github.com/Q42/CATiledLayerBug/blob/master/TiledLayerTest/ViewController.swift#L45

    screenshot

    解决方法

    这似乎是CATiledLayer实施中的一个错误。由于我无法解决这个问题,有没有人知道这个问题的一个好的解决方法?

    我为此提出了一个雷达:http://www.openradar.me/28648050

1 个答案:

答案 0 :(得分:2)

基于我添加到示例项目中的一些进一步的日志记录,我认为问题是:

CATiledLayer有两个绘制每个图块的渲染线程。如果在执行draw(_: CGRect)调用期间调用了setNeedsDisplay,则draw调用的当前执行结束并且结果被缓存。缓存的值基于先前的“数据源”(本示例中仅为tile颜色),而不是更新的数据源。

Apple支持工程师为我提供了一种解决方法:

  • updateID字段添加到TiledView
  • 添加draw(_: CGRect)来电的开头,保存当前updateID
  • 当“数据源”发生变化时,请更改updateID
  • 添加draw(_: CGRect)来电的结尾,将保存的updateID与当前的setNeedsDisplay进行比较。
  • 如果ID不同,请安排新的override func draw(_ rect: CGRect) { let originalID = updateID // all actual (slow) drawing code here... if originalID != updateID { // dispatch a redraw request, but wait a little while first DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(17)) { self.layer.setNeedsDisplayIn(rect) } } } 来电。

提取物:

archivo