drawRect: 不为带有 CAMetalLayer 的 NSView 调用
drawRect: Not called for an NSView with a CAMetalLayer
我有一个 layer-backed(not layer-hosted)子类 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 方法未被调用。我尝试将 wantsUpdateLayer 设置为 true。 render 方法被调用,我删除了这部分:
wantsLayer = true
metalLayer.delegate = self
metalLayer.device = MTLCreateSystemDefaultDevice()
metalLayer.pixelFormat = .BGRA8Unorm
metalLayer.framebufferOnly = true
来自 wantsLayer
文档:
If the wantsUpdateLayer method returns NO, you should not interact with the underlying layer object directly.
在 metalLayer
上设置值并将其帧数修改为 "interact[ing] with the underlying layer object directly." 您不能在此配置中执行此操作。该图层不属于您。它属于系统。系统可以随时自由创建这些缓存层。它不必使用它,也不必只有一个。 (Core Animation 通常会创建额外的图层;这是完全正常的。)
如果您想直接与图层交互,您应该将 wantsUpdateLayer
设置为 true
,然后在 updateLayer
中实现您的绘图代码。您不应该尝试将 drawRect:
与您直接弄乱的层混合。
有关此问题的另一个版本,请参阅
我有一个 layer-backed(not layer-hosted)子类 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 方法未被调用。我尝试将 wantsUpdateLayer 设置为 true。 render 方法被调用,我删除了这部分:
wantsLayer = true
metalLayer.delegate = self
metalLayer.device = MTLCreateSystemDefaultDevice()
metalLayer.pixelFormat = .BGRA8Unorm
metalLayer.framebufferOnly = true
来自 wantsLayer
文档:
If the wantsUpdateLayer method returns NO, you should not interact with the underlying layer object directly.
在 metalLayer
上设置值并将其帧数修改为 "interact[ing] with the underlying layer object directly." 您不能在此配置中执行此操作。该图层不属于您。它属于系统。系统可以随时自由创建这些缓存层。它不必使用它,也不必只有一个。 (Core Animation 通常会创建额外的图层;这是完全正常的。)
如果您想直接与图层交互,您应该将 wantsUpdateLayer
设置为 true
,然后在 updateLayer
中实现您的绘图代码。您不应该尝试将 drawRect:
与您直接弄乱的层混合。
有关此问题的另一个版本,请参阅