【问题标题】:CATiledLayer requests the same tile multiple timesCATiledLayer 多次请求同一个图块
【发布时间】:2011-04-03 17:49:24
【问题描述】:

请看这个简单的 CATiledLayer 示例https://github.com/seanhess/CATiledLayer-Example

它由一个具有如下层次结构的 viewController 组成:

view: (frame = window size)
    scrollView: (frame = window size, content size = 200 x 4000)
        contentView: (frame = content size = 200 x 4000, tile size = 100 x 100)

内容视图的图层已被覆盖为 CATiledLayer。

如果您运行链接代码,您会看到多次请求具有相同矩形的图块。它在您第一次运行代码和滚动时都会发生。

切换到“单列”分支 - 它只发生在初始化时,从不发生在您向下滚动时。

切换到分支“default-tile-size”——它只发生在 init 上,但很少发生(你必须在它发生之前多次运行它)

我正在尝试在drawLayer:inContext: 中编写一些代码来定位正确的数据并绘制它。它可能很昂贵,我不想多次这样做。

知道发生了什么吗?我能做些什么不同的事情?

【问题讨论】:

  • 我怀疑没有人真正了解CATiledLayer,除了用它来绘制巨大的图像。 :(关于去哪里寻求帮助的建议?
  • 我也看到了同样的情况。我有一个小型演示应用程序,只有 12 个图块在屏幕上显示而无需滚动,并且绘图代码被调用 22 次。我也会继续研究这个。
  • 在 CATiledLayer 的其他问题中,我想知道同样的问题。也许您可以单独跟踪已请求哪些图块,并简单地跳过已请求的矩形的昂贵操作?
  • @TheBlack - 这就是我最终所做的,但我会在下面查看 EricK 的东西。

标签: iphone cocoa-touch ios catiledlayer


【解决方案1】:

这是 IOS 中的一个错误。当 CPU 是双核时会发生这种情况,在这种情况下,有两个线程分别请求每个 tile。这意味着该错误存在于模拟器和 iPhone 4S 上,但不存在于其他 iPhone 型号上。我认为它也将出现在双核 iPad 上。

我很久以前(针对模拟器)和最近(针对 iPhone 4S)向 Apple 报告了该错误。 Apple 最近给人的印象是他们已经在 IOS 6 中解决了这个问题。

【讨论】:

  • 我在这里看到了相同的行为,但没有机会在 iOS 6 上对其进行测试。一旦 iOS 6 离开测试版,我们将不胜感激。
  • Apple 已要求我在 iOS 6 beta 上测试该错误。但我现在还没有能力这样做(我已经切换到我自己的平铺层实现)。但如果有人在 iOS 6 beta 上测试它,那么我可以将结果报告给 Apple。
  • 我最近在 iOS 6.0.1 上报告了这个问题,它被标记为与另一个问题重复。我在 Apple 的 bugreporter 上看不到其他问题,但我可以看到它的状态仍然是“打开”
  • 我刚刚在 iOS 6.0.1 上重新测试了这个,它似乎在设备本身上得到了解决(至少在带有 6.0.1 的 iPhone 4S 上)。然而它仍然没有在模拟器上解决。并且 setNeedsDisplay 错误也没有解决:如果在绘制过程中调用 setNeedsDisplay(这很难避免......),您仍然可以通过两个线程并行重绘同一个图块。仅供参考,我在模拟器上的原始错误是 10456864(重复),对于 iPhone 4S:11768030(已关闭)。 setNeedsDisplay 错误:10456578(打开)
  • @fishinear 您切换到自己的解决方案了吗?我也需要那个。你能帮助我吗?您可以通过电子邮件与我联系。
【解决方案2】:

这里解决得很好:

https://stackoverflow.com/a/8783396/341994

问题是(至少在我的测试中)drawRect: 在两个线程上同时被调用。通过记录,我可以看到我的代码的各个行在我们继续执行下一行之前被执行了两次,这也被执行了两次!日志显示这是因为一个线程正在执行一行,然后另一个线程正在执行同一行 - 然后它们都继续执行下一行。

这真是令人讨厌。解决方案是将drawRect: 的整个内部包装在串行队列上的dispatch_sync 中。

【讨论】:

    【解决方案3】:

    您是否在设备上尝试过您的代码?我一直在模拟器中看到这种行为,但在我的 iPad 1 上没有。我刚刚在一个显示大平铺图像的应用程序中再次尝试了这个。我的图块大小为 256,在设备上我的 drawRect: 方法被调用了 12 次,即屏幕上有多少图块。在模拟器中,该方法被调用了 20 到 23 次,除了最后几个图块之外的所有图块都被绘制了两次。

    【讨论】:

    • 我已经在 iPhone 4S 上进行了测试,它存在于那里。 iPad 1 是单核的,这就解释了为什么这个 bug 没有出现。我预计 iPad 2 和 3 上也会出现该错误。
    【解决方案4】:

    这不是因为 setLevelsOfDetailBias 吗?当我将所有内容保持标准时,瓷砖只会渲染一次(在设备上进行测试)。但是当我将 levelofdetailbias 设置为 2 时,瓷砖会被多次加载。我认为这是因为 CATiledLayer 只是在设备空闲时才开始缓存额外的细节级别。

    【讨论】:

      【解决方案5】:

      最后,答案没有用。但是,让您的委托方法知道它是否已经绘制了该循环是相当简单的。

      【讨论】:

      • 实际上,如果您的绘图周期很接近,这可能比您预期的要困难。特别是因为 CATiledLayer 中的另一个错误:当您在绘制图块的过程中调用“setNeedsDisplay”时,它不会重绘该图块。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-10
      • 1970-01-01
      • 2015-10-02
      相关资源
      最近更新 更多