1

I am trying to run a display link in a thread other than main but it simply doesn't work. I have a simple dispatch queue created like queue = DispatchQueue(label: "xyz") and then I create the display link as usual:

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

The selector never gets called. Upon checking the currentMode of the RunLoop I see it is nil. What am I missing?

Thanks

xissburg
  • 618
  • 5
  • 14
  • 3
    Background threads aren’t [running](https://developer.apple.com/documentation/foundation/runloop/1412430-run) a run loop like the main thread does, unless you manually do so. But this is a Core Animation object and all UI stuff should happen on the main queue. If you want a background timer, you’d use a GCD timer. Why would you want to run this on a background thread? – Rob May 04 '19 at 09:49
  • @Rob I am profiling the code and found that a call to `CIContext.render` is quite slow and that is apparently causing the overall app fps to drop (most noticeable on scroll views). So I think I will have to run the display link in the main thread as it should and do a dispatch async for the render. – xissburg May 05 '19 at 19:36
  • Sure, by dispatching it to another queue, you can make sure it will get called at the max frame rate, but it’s going to get hopelessly backlogged. Usually you’d either live with the dropped frames, or focus on optimizing the rendering so fewer frames are dropped. FWIW, I frequently find CoreImage to be a great API that is just too slow for many practical animations and that I often have to dive into other more complicated mechanisms like [vImage](https://developer.apple.com/documentation/accelerate/vimage) or Metal or whatever. It depends entirely upon what you’re doing in your render process. – Rob May 05 '19 at 21:31

1 Answers1

1

Due to the reason that your queue is non-main, the current run loop won't trigger by itself.

You should call current.run() manually after displayLink been added.

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