Macos drawRect:对于具有CametLayer的NSView,未调用

Macos drawRect:对于具有CametLayer的NSView,未调用,macos,calayer,nsview,metal,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 awakeFromNi

我有一个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")
    }

}
未调用render方法。我尝试将WANTSUPDatalayer设置为true。使用I remove此部分调用render方法:

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

wantsLayer
文档:

如果wantsUpdateLayer方法返回否,则不应直接与底层对象交互

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

如果要直接与图层交互,应将
wantsUpdateLayer
设置为
true
,然后在
updateLayer
中实现图形代码。您不应该尝试将
drawRect:
与直接处理的层混合


有关此问题的另一个版本,请参见

我尝试将
wantsUpdateLayer
设置为
true
并覆盖
updateLayer
,但也不起作用。我还尝试将设置层的代码移动到
makeBackingLayer
@GorGyolchanyan在设置WantUpdateLayer后,当您调用setNeedsDisplay时不会调用updateLayer?我手动调用了
metalLayer.setNeedsDisplay()
,它只会导致方法
displayLayer(layer:CALayer)无论WANTSUPDatalayer如何调用
。问题是它在调整视图大小时不会被调用。这是默认设置。您是否设置了layerContentsRedrawPolicy?除非您明确要求,否则图层通常避免重画。默认情况下,绝对不会进行边界更改(除非您要求完全重画,否则它们只是缩放或平移)。是的,确实有效,非常感谢。不过,另一个问题仍然存在:当我更新视图时,视图会闪烁并出现大量故障。