macos - 使用 NSView 进行图层支持绘图时不会调用 drawRect

标签 macos calayer nsview metal

我正在尝试将我的 Opengl 应用程序迁移到 Metal,并且我正在使用 CAMetalLayer 来实现 Metal。 我在继承的 NSView 类对象上设置了以下属性:

self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
[self setWantsLayer:YES];

我已经检查了其他答案,例如 NSView subclass - drawRect: not called

因此,我尝试按照上面答案中的建议分配委托(delegate),如下所示

[self.layer setDelegate:self];

我收到以下编译错误:

Cannot initialize a parameter of type 'id<CALayerDelegate> _Nullable' with an lvalue of type 'MyNSView *'

此外,我还在https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/SettingUpLayerObjects/SettingUpLayerObjects.html处看到了设置图层对象的文档。 ,其中指出:

For layer-backed views with custom content, you should continue to override the view’s methods to do your drawing. A layer-backed view automatically makes itself the delegate of its layer and implements the needed delegate methods, and you should not change that configuration. Instead, you should implement your view’s drawRect: method to draw your content.

因此,根据此,我什至不必在我的情况下设置委托(delegate),并且我已经在 MyNSView 中实现了 drawRect 函数。但它仍然没有被调用。

还有什么需要做的吗?

谢谢!

编辑: 因此,我通过使我的层遵循协议(protocol) CALayerDelegate 来修复编译错误,但仍然没有收到对drawLayer或drawRect的任何调用.

makeBackingLayer

- (CALayer*)makeBackingLayer
{
    id <MTLDevice> device = MTLCreateSystemDefaultDevice();
    CAMetalLayer *backingLayer   = [CAMetalLayer layer];
    backingLayer.opaque          = YES;
    backingLayer.device          = device;
    backingLayer.pixelFormat     = MTLPixelFormatBGRA8Unorm;
    backingLayer.framebufferOnly = YES;

//    [backingLayer setDelegate:self]; //Tried setting the delegate 
                                       //here as well

    return backingLayer;
}

初始化函数

self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
[self setWantsLayer:YES];
[self.layer setDelegate:self];

绘制函数

- (void)displayLayer:(CALayer *)layer
{
    [self drawRect:self.bounds];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    [self drawRect:self.bounds];
}

-(void) drawRect: (NSRect) dirtyRect
{
    [super drawRect:dirtyRect];
}

我已经实现了所有绘制函数来检查它们中是否有任何函数被击中,但我没有收到对任何这些函数的调用。

为了将内容绘制到 NSView,我绘制到屏幕外资源,并从 NSView 的 CALayer 获取 drawable 并在提交 commandBuffer< 之前调用 presentDrawable/.

最佳答案

由于这里没有太多内容可供我调试以查找引入错误的位置,因此我开始研究指令的执行顺序。事实证明,您调用的顺序:

[self setWantsLayer:YES];
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;

导致了这个问题。在交换这两个语句时,我开始收到对我的 displayLayer 函数的调用。我仍然不明白为什么 drawRect 没有被图层支持的 NSView 调用。

发布此内容是为了防止此交换也能解决其他人的问题。

关于macos - 使用 NSView 进行图层支持绘图时不会调用 drawRect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53042498/

相关文章:

ios - Flash 在 OS X/iOS 上不工作?

ios - UIImageView 阴影和纵横比填充在一起

cocoa - Swift 3 加载 xib。 NSBundle.mainBundle().loadNibNamed 返回 Bool

cocoa - 为什么 "add subview"不起作用?

cocoa - NSSplitView subview 大小以编程方式限制为容器 NSSplitView 的大小

macos - 多行 NSTextField 不起作用

macos - 如何将 Sprite Kit View 的屏幕截图保存到 png 文件或剪贴板?

ios - 为什么CALayer的类别可以声明一个属性而不需要实现并直接使用它?

ios - 如何从表示层创建新的 CALayer?

cocoa - 根据表格列的 isEnabled 出价自定义 NSTextFieldCell