Cocoa 在层承载视图上调用setNeedsDisplay:YES不会重新绘制视图

Cocoa 在层承载视图上调用setNeedsDisplay:YES不会重新绘制视图,cocoa,core-animation,Cocoa,Core Animation,我在自定义NSView子类中设置了一个层宿主视图,如下所示: [self setLayer:rootLayer]; [self setWantsLayer:YES]; 在调用每个子层上的setNeedsDisplay后,我将所有子层添加到层树中。每个层的内容都由我的层代理的drawLayer:inContext方法提供 我的问题是: 初始化视图后,视图将正确绘制。但是,当模型发生变化时,我调用[myCustomView setNeedsDisplay:YES]从我的视图控制器中,不调用绘图层:

我在自定义
NSView
子类中设置了一个层宿主视图,如下所示:

[self setLayer:rootLayer];
[self setWantsLayer:YES];
在调用每个子层上的
setNeedsDisplay
后,我将所有子层添加到层树中。每个层的内容都由我的层代理的
drawLayer:inContext
方法提供

我的问题是:

初始化视图后,视图将正确绘制。但是,当模型发生变化时,我调用
[myCustomView setNeedsDisplay:YES]从我的视图控制器中,不调用
绘图层:inContext

我现在不知道如何更新视图:

[self setLayer:rootLayer];
[self setWantsLayer:YES];
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
  • 我是否必须在层树中的每个层上调用
    setNeedsDisplay
    方法
  • 在图层宿主视图本身上调用
    setNeedsDisplay:YES
    是否应该触发整个图层树的重画
谢谢你的帮助

编辑

我在NSView类参考中找到了一些内容

层备份视图是由核心动画层备份的视图。视图完成的任何图形都会缓存在背衬层中。您只需调用值为YES的setWantsLayer:即可配置层备份视图。view类将自动为您创建背景层,您可以使用view类的绘图机制。使用图层备份视图时,决不应直接与图层交互

层宿主视图是包含要直接操纵的核心动画层的视图。通过实例化核心动画层类的实例并使用视图的setLayer:方法设置该层,可以创建承载视图的层。执行此操作后,然后使用值YES调用setWantsLayer:。使用图层主体视图时,不应依赖该视图进行绘图,也不应向图层主体视图添加子视图


在我的例子中,我有一个层托管视图。那么这真的意味着我必须手动触发重画吗?我是否应该在自定义NSView中实现一个伪drawRect方法,以便在更改的Calayer上调用相应的setNeedsDisplay?

在进一步研究Apple的kiosk样式菜单后,我发现如果您使用的是层宿主视图,您必须注意屏幕更新,这是由于您自己更改了模型所必需的。在NSView上调用
setNeedsDisplay:YES
将不起任何作用

因此,如果必须更新视图,则必须编写一个类似reloadData的方法,并在其中对每个需要刷新的CALayer调用
setNeedsDisplay
。我仍然不确定根层上对该方法的调用是否会传播到所有子层,但我不这么认为


我现在通过调用需要重新校准的各个Calayer上的
setNeedsDisplay
解决了这个问题。它可以毫无问题地工作。

还有一种常用的做法,即使用一个空的“drawrect”,一个la
-(void)drawrect:(NSRect)dirtyRect{}
来帮助将内容强制到绘图中,我相信这是通过良好的ole
视图实现的。needsDisplay=YES

值得注意的是。。实际上发生的是——通过说出你的
NSView*视图
layer.delegate=视图导致在
[图层设置需要显示]时绘制图层被称为。。。。via
-(void)drawLayer:(CALayer*)层inContext:(CGContextRef)ctx{…}

同样的道理。。。当说
layer.layoutManager=view
。。。
[layer setNeedsLayout]的后续需求-(void)layoutSublayersOfLayer:(CALayer*)layer{..}
方法时,才会实现code>


这些重要的概念在苹果的文档中被掩盖了。。。而且它们对于使任何东西都能正常工作来说都是非常关键的。

通过更改视图的重画策略,您可以自动委托
设置需要显示:
。您必须将
nsviewLayerContentsRedawOnSetNeedsDisplay
分配给属性
LayerContentsRedawPolicy
(请参阅)。当您将
setNeedsDisplay:
发送到视图时,这将触发图层的重绘:

[self setLayer:rootLayer];
[self setWantsLayer:YES];
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
或使用Swift:

layer = rootLayer
wantsLayer = true
layerContentsRedrawPolicy = .onSetNeedsDisplay

您与示例代码的链接已断开,也许这是替换:您能解释一种对初学者更友好的方式吗?@carbor我知道这很混乱。但我所说的很简单。如果显示不正确,并且您的视图是图层的代理。。您需要实现
drawLayer:inContext
,并且可能有一个空的
drawRect:
并调用
setNeedsDisplay
。如果有必要的话,读10遍,但是信息都在那里。如果我没记错的话,那就是