CATiledLayer drawLayer:inContext 总是在主线程上被调用 - MacOS El Capitan

7
我正在使用一个由CATiledLayer支持的NSView(Mac而不是iOS),根据苹果文档https://developer.apple.com/reference/quartzcore/catiledlayer,我希望这个任务在多个线程上异步调用以提高性能,但它似乎只在主线程上被调用。
我在drawLayer(layer: CALayer, inContext ctx: CGContext)中完成工作。
我已经在NSView上启用了canDrawConcurrently,并确保窗口已设置allowsConcurrentViewDrawing为true(默认值),但它仍然总是为每个tile rect调用主线程。
在显示之前,我需要进行一些图像操作,这需要依赖于需要显示的矩形区域,并且在主线程上运行会影响性能。
有什么办法可以强制它在后台线程上调用吗?
我已经尝试将图像驱动器调度到后台线程上,然后调用以下主队列,但它会显示空白矩形:
backgroundQueue.addOperationWithBlock({ [ weak self ] in            
    guard let strongSelf = self else { return }

    // ** This is the part I nee to do in background that can take some time
    guard let image = strongSelf.imageForTileRect(layerBounds, imageSize: imageSize) else { return }
    // ** End background bit

    var rect = layerBounds
    let rectImageRef = image.CGImageForProposedRect(&rect, context: nil, hints: nil)

    if (rectImageRef != nil) {
        NSOperationQueue.mainQueue().addOperationWithBlock({ 
            CGContextDrawImage(ctx, rect, rectImageRef)
        })
    }
})

你解决了这个问题吗?我也遇到了同样的情况。我想使用后台线程来绘制我的NSView的CATiledLayer。 - Stephen Johnson
这里还有一些上下文。 如果我将另一个CATiledLayer作为覆盖层添加到作为我的背景覆盖层的那个上面,它会在后台渲染。只有作为我的视图背景的主要部分在主线程上进行渲染。我可能最终会使主要部分为空白,并将我的渲染放到一个覆盖层的CATiledLayer中。 - Stephen Johnson
2个回答

2
我们尝试将CATiledLayer作为主要图层使用时,无法使其正常工作。不确定原因,我们也没有得到苹果提出的错误的答复。
然而,通过将主要图层设置为标准的CALayer,然后将CATiledLayer作为此主要图层的子层添加,我们成功实现了后台渲染,代码类似于下面的示例。
我们还注意到,如果将CATiledLayer托管在NSView中,则可以按预期工作。
希望这有所帮助...
class HostingLayer : CALayer {

    var tiledLayer : CATiledLayer!

    override init() {
        super.init()

        self.tiledLayer = CATiledLayer.init()

        self.addSublayer(tiledLayer!)
    }
}

0

所以这是我做的,虽然不是理想的方法。在我的CATiledLayer支持的NSViewdrawRect:中,我绘制了一个简单的背景(在我的情况下是一个简单的网格)。我创建了另一个CATiledLayer并将其添加到我的NSView的层作为子层,并将NSView设置为其代理。第二个`CATiledLayer'在后台线程上获取代理绘制调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接