2016-02-28 48 views
0

我有一個層支持層託管)的子類的NSView稱爲MetalView的drawRect:不呼籲的NSView與CAMetalLayer

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") 
    } 

} 

渲染方法沒有被調用。我試過設置wantsUpdateLayertrue。該渲染方法被調用與我刪除了這部分:

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

回答

2

wantsLayer文檔:

如果wantsUpdateLayer方法返回NO,你不應該直接與底層對象交互。

metalLayer上設置值並將其幀數修改爲「直接與底層對象交互[」]。在這種配置中,你不能這麼做。該圖層不屬於你。它屬於系統。系統可以隨時創建這些緩存層。它不必使用它,並且不一定只有一個。 (核心動畫往往會造成額外的層,這是完全正常的。)

如果您想直接與層交互,你應該設置wantsUpdateLayertrue,然後在updateLayer實現繪圖代碼。您不應該嘗試將drawRect:與您直接混淆的圖層混合。

對於這個問題的另一個版本,看到Why is an empty drawRect interfering with a simple animation?

+0

我試着設置'wantsUpdateLayer'到TRUE;並覆蓋'updateLayer',但它也不管用。我也嘗試將設置圖層的代碼移動到'makeBackingLayer'中。 –

+0

@GorGyolchanyan在設置wantsUpdateLayer之後,當你調用setNeedsDisplay時,updateLayer不會被調用? –

+0

我已經手動調用了'metalLayer.setNeedsDisplay()',並且它只會導致調用displayLayer(layer:CALayer)方法,而不管使用'wantsUpdateLayer'。問題是它沒有被調用來調整視圖的大小。 –