CADisplayLink 回调是否总是在主线程上运行?

Is CADisplayLink callback always runs on the main thread?

我在网上和文档中都找不到任何直接的答案。 如果我使用以下设置 CADisplayLink

 let displayLink = CADisplayLink(target: self, selector: #selector(updateShimmer))
 displayLink.add(to: .current, forMode: .common)

@objc func updateShimmer() {
   print(Thread.isMainThread)
}

我说真的。我知道我可以将它包装在 DispatchQueue.main 中,但我想知道,它是否总是在主队列上调度?还是我应该把它包起来?

您不需要手动将显示 link 处理程序中的代码分派到主线程。添加到特定 运行 循环的计时器和显示 links 将始终 运行 在与该 运行 循环关联的线程上。有关详细信息,请参阅 Threading Programming Guide: Run Loops

底线,如果您 add(to:forMode:) 到主 运行 循环,主 运行 循环总是 运行 在主线程上。

话虽这么说,如果您想确保它始终 运行 在主线程上,我建议明确并将其添加到 .main,而不仅仅是 .current.这消除了任何歧义:

let displayLink = CADisplayLink(target: self, selector: #selector(updateShimmer(_:)))
displayLink.add(to: .main, forMode: .common)

注意,我还调整了 updateShimmer 的签名以接受参数。显示 link 将传递给它。在方法中包含该引用通常很有用。而且,无论如何,它使一个人的代码更加不言自明:您现在只需看一眼这个方法就可以理解这是一个显示 link 处理程序:

@objc func updateShimmer(_ displayLink: CADisplayLink) {
     ...
}