【问题标题】:CADisplayLink in a DispatchQueueDispatchQueue 中的 CADisplayLink
【发布时间】:2019-09-22 13:21:16
【问题描述】:

我试图在除主线程之外的线程中运行显示链接,但它根本不起作用。我创建了一个简单的调度队列,如queue = DispatchQueue(label: "xyz"),然后像往常一样创建显示链接:

queue.async {
  self.displayLink = CADisplayLink(target: self, selector: #selector(render))
  self.displayLink.add(to: .current, forMode: .common)
}

选择器永远不会被调用。检查RunLoopcurrentMode 后,我发现它为零。我错过了什么?

谢谢

【问题讨论】:

  • 后台线程不是running 像主线程那样的运行循环,除非你手动这样做。但这是一个核心动画对象,所有 UI 内容都应该发生在主队列上。如果你想要一个后台计时器,你会使用 GCD 计时器。为什么要在后台线程上运行它?
  • @Rob 我正在分析代码,发现对CIContext.render 的调用非常慢,这显然导致整个应用程序的 fps 下降(在滚动视图上最明显)。所以我想我必须在主线程中运行显示链接,并为渲染执行异步调度。
  • 当然,通过将它分派到另一个队列,您可以确保它会以最大帧速率被调用,但它会毫无希望地积压。通常你要么忍受丢帧,要么专注于优化渲染以减少丢帧。 FWIW,我经常发现 CoreImage 是一个很棒的 AP​​I,它对于许多实际动画来说太慢了,而且我经常不得不深入研究其他更复杂的机制,例如 vImage 或 Metal 或其他。这完全取决于您在渲染过程中所做的工作。

标签: ios grand-central-dispatch cadisplaylink dispatch-queue


【解决方案1】:

由于你的队列是非主队列,当前的运行循环不会自己触发。

您应该在添加 displayLink 后手动调用current.run()

queue.async {
  self.displayLink = CADisplayLink(target: self, selector: #selector(render))
  let current = RunLoop.current
  self.displayLink.add(to: current, forMode: .common)
  current.run()
}

【讨论】:

    猜你喜欢
    • 2021-04-28
    • 2017-03-30
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-01
    相关资源
    最近更新 更多