提问人:Brew Master 提问时间:5/15/2023 最后编辑:Brew Master 更新时间:5/25/2023 访问量:436
如何在后台线程上呈现 CALayer 的内容
How to Render Content of CALayer on a Background Thread
问:
我正在实现一个需要在后台线程上执行绘图的 CALayer。但是,尽管将属性“drawsAsynchronously”设置为 true,但仍在主线程上调用 draw 函数。这是我目前的实现:
class DKVectorLayer : CALayer {
private let renderQueue = DispatchQueue( label: "Render queue, qos: .userInitiated)
override func draw(in ctx: CGContext) {
// This is still running in the main thread
}
}
我尝试使用“renderQueue.async”将渲染代码移动到后台队列,但它似乎没有按预期工作。在“renderQueue.async”闭包中执行的绘图代码似乎被忽略,并且绘制发生在“draw(in:)”函数之后。
override func draw(in ctx: CGContext) {
renderQueue.async {
// Render code here, but it does not display on the screen
}
}
有没有办法在后台线程上呈现 CALayer 的内容?我知道 CATiledLayer 可以在后台线程上呈现内容,但它有一些限制。例如,在调用“setNeedsDisplay(in: rect)”时,将忽略指定的矩形,并重新绘制所有图块。
答:
完成后,必须完全绘制图层。不能通过在 内部调度来延迟绘制。但是,CALayer 是线程安全的,您可以自由地调用另一个线程并自行管理图层绘制。结果将被绘制到您传递的 CGContext 中。您还可以创建一个 CGImage 并将其分配给属性,只要这不是图层支持的视图。draw(in:)
draw(in:)
draw(in:)
content
drawsAsynchronously
不确定在何处执行。它确定最终呈现发生的位置(将 CGContext 指令转换为位图)。 不生成位图。它只是创建指令。draw(in:)
draw(in:)
如果图层作为视图层次结构的一部分进行渲染,则它将在系统选择的线程上发生(这通常是主线程,但在动画期间可能不是主线程)。通常,你要做的是在后台线程上计算所有昂贵的内容并缓存它,所以当 UIKit 或 AppKit 要求绘制图层时,它的速度会很快。
评论
UIGraphicsImageRenderer