Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 在NSOutlineView中承载NSView的层_Objective C_Macos_Cocoa_Calayer_Nsoutlineview - Fatal编程技术网

Objective c 在NSOutlineView中承载NSView的层

Objective c 在NSOutlineView中承载NSView的层,objective-c,macos,cocoa,calayer,nsoutlineview,Objective C,Macos,Cocoa,Calayer,Nsoutlineview,我正在尝试创建一个自定义的NSView,它承载一个CALayer层次结构,以执行有效的显示。然后,此NSView被嵌入到基于视图的NSOutlineView显示的NSTableCellView中 问题是,每当我展开或折叠一个项目时,所有行都会被移动,但图层的内容仍显示在更改轮廓之前的位置 滚动NSOutlineView似乎会刷新图层,此时图层与行重新同步 我已经用仪器调试过这种行为,滚动似乎引发了一个布局操作,该操作使用setPosition:调用更新图层,该调用应该在展开或折叠项目时发生 下面

我正在尝试创建一个自定义的
NSView
,它承载一个
CALayer
层次结构,以执行有效的显示。然后,此
NSView
被嵌入到基于视图的
NSOutlineView
显示的
NSTableCellView

问题是,每当我展开或折叠一个项目时,所有行都会被移动,但图层的内容仍显示在更改轮廓之前的位置

滚动
NSOutlineView
似乎会刷新图层,此时图层与行重新同步

我已经用仪器调试过这种行为,滚动似乎引发了一个布局操作,该操作使用
setPosition:
调用更新图层,该调用应该在展开或折叠项目时发生

下面是托管
NSView
子类的简单层的一些示例代码

@interface TestView : NSView

@end

@implementation TestView

- (instancetype)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    CAShapeLayer* layer = [CAShapeLayer layer];
    layer.bounds = self.bounds;
    layer.position = CGPointMake(NSMidX(self.bounds), NSMidY(self.bounds));
    layer.path = [NSBezierPath bezierPathWithOvalInRect:self.bounds].CGPath;
    layer.fillColor = [NSColor redColor].CGColor;
    layer.delegate = self;
    self.layer = layer;
    self.wantsLayer = YES;
    return self;
}

@end
我已经尝试了很多解决这个问题的潜在方法,但是我找不到任何在
NSView
实例上调用的有趣方法,这些方法可以被覆盖以调用
[self.layer setNeedsDisplay]
[self.layer setNeedsLayout]
。我还尝试了
CALayer
本身的各种设置,例如:

layer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
layer.needsDisplayOnBoundsChange = YES;
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;

有谁能帮我弄清楚如何在
NSOutlineView
中正确显示此层吗?

阅读
NSOutlineView
参考文档并找到可能让您适合这里的有关单元重用的信息是很困难的

您可能已经看过了
outlineViewItemDidCollapse:
,但对于我们的问题来说,它是一个无用的工具,因为它没有指向
NSView
的指针,这是因为它比基于视图的大纲视图旧

outlineView:didRemoveOWView:forRow:
中关于基于视图的NSOutlineView方法的部分中,可能有一个有用的提及,隐藏在
NSOutlineView:forRow:
协议中:

删除的行视图可能会被表重用,因此此时应删除任何额外插入的视图

换句话说,当您调用outline视图的
makeViewWithIdentifier:owner:
时,对于具有特定ID的cellView或rowView,您通常会得到一个循环视图。尤其是因为坍塌。顺便说一句,该方法来自
NSTableView
超类,在该引用中,还有:

此方法还可能返回一个重用视图,该视图具有屏幕上不再可用的相同标识符。如果无法从nib文件实例化具有指定标识符的视图,或者无法在重用队列中找到该视图,则此方法返回nil

因此,您可以在
didRemoveRowView:forRow
中选择更改视图层次结构或niling属性。但是,在第三个cocoa参考中,即对于
NSView
,在
prepareforeuse
的注释中

此方法提供了一种将视图重置为某些初始状态的方法,以便可以重用该视图。例如,NSTableView类使用它来准备视图以供重用,从而避免在视图滚动到视图中时创建新视图的开销。如果您在自己的代码中实现了视图重用系统,则可以在重用它们之前从自己的代码中调用此方法

因此,TL;DR,您需要实施
prepareforeuse

相关参考(主要)是
NSOutlineView
NSTableCellView
的超类

而且,FWIW,有一个问题,提问者似乎指出事情比我想象的更糟,因为NSOutlineView在幕后比NSTableView更具创造性


在我自己使用outline视图和嵌入式NSTextView的工作中,我看到了与展开/折叠/滚动相关的非常糟糕的渲染问题,我似乎只在NSOutlineViewDeleteGate方法中处理了这些问题。在iOS上,他们帮了大家的忙,将
makeViewWithIdentifier
重命名为更明确的
dequeueReusableCellViewWithIdentifier

,最后我回答了我的问题。问题不在于我的TestView的实现方式。我只是错过了在应用程序中启用CoreAnimation支持的一个步骤。相关参考在核心动画编程指南中

基本上,在iOS内核中,默认情况下始终启用动画和层备份。在OS X上,必须通过以下方式启用:

  • 与QuartzCore框架的链接
  • 通过执行以下操作之一,为一个或多个NSView对象启用层支持
    • 在nib文件中,使用视图效果检查器为视图启用图层支持。检查器将显示选定视图及其子视图的复选框。建议尽可能在窗口的内容视图中启用层支持
    • 对于以编程方式创建的视图,请调用视图的setWantLayer:方法,并传递值YES以指示视图应使用层

  • 一旦我在NSOutlineView的任何父视图上启用了层支持,各种小故障就解决了。

    您不必为任何祖先视图(如大纲视图)启用层备份

    根据我的经验,立即指定给视图的层(与子层相反)不需要设置其边界、位置或自动调整大小的遮罩。将自动使其跟踪视图的边界。事实上,我会避免设置这些属性,以防破坏与视图的bounds rect的自动同步

    因此,问题是:您如何安排视图随其superview移动或调整大小?你在使用自动布局吗?如果是,您是否关闭了其
    翻译自动调整大小GMaskintoConstraints
    ?如果两者均为“是”,则在视图上设置哪些约束?如果其中一个都没有,您是如何定位视图w的