drawRect:没有使用CAMetalLayer调用NSView

时间:2016-02-28 14:03:30

标签: macos calayer nsview metal

我有一个图层支持的 图层托管的 NSView 的子类,名为 MetalView

import Cocoa
import Metal

class MetalView: NSView {

    // MARK: Properties

    var metalLayer: CAMetalLayer {
        return layer as! CAMetalLayer
    }

    // MARK: - Overrides

    override func awakeFromNib() {
        super.awakeFromNib()
        initialize()
    }

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)
        render()
    }

    override func drawLayer(layer: CALayer, inContext ctx: CGContext) {
        super.drawLayer(layer, inContext: ctx)
        render()
    }

    override func displayLayer(layer: CALayer) {
        super.displayLayer(layer)
        render()
    }

    override func makeBackingLayer() -> CALayer {
        return CAMetalLayer()
    }

    override var wantsUpdateLayer: Bool {
        return false
    }

    // MARK: - Initialization

    func initialize() {
        // Layer
        wantsLayer = true
        metalLayer.delegate = self
        metalLayer.device = MTLCreateSystemDefaultDevice()
        metalLayer.pixelFormat = .BGRA8Unorm
        metalLayer.framebufferOnly = true
    }

    // MARK: - Rendering

    func render() {
        // Rendering
        metalLayer.frame = frame
        NSLog("rendering")
    }

}

未强制调用渲染方法。我尝试将 wantsUpdateLayer 设置为 true 。调用渲染方法,我删除此部分:

wantsLayer = true
metalLayer.delegate = self
metalLayer.device = MTLCreateSystemDefaultDevice()
metalLayer.pixelFormat = .BGRA8Unorm
metalLayer.framebufferOnly = true

1 个答案:

答案 0 :(得分:3)

来自wantsLayer文档:

  

如果wantsUpdateLayer方法返回NO,则不应直接与底层图层对象进行交互。

metalLayer上设置值并将其帧数修改为“直接与底层图层对象交互”。您不允许在此配置中执行此操作。该图层不属于您。它属于该系统。系统可以随时创建这些缓存层。它不必使用它,也不必只是一个。 (核心动画通常会创建额外的图层;这是完全正常的。)

如果您想直接与图层互动,则应将wantsUpdateLayer设置为true,然后在updateLayer中实施图纸代码。您不应该尝试将drawRect:与您直接混乱的图层混合在一起。

有关此问题的其他版本,请参阅Why is an empty drawRect interfering with a simple animation?