【问题标题】:Are layer-hosting NSViews allowed to have subviews?托管层的 NSView 是否允许有子视图?
【发布时间】:2012-05-29 23:13:05
【问题描述】:

Layer-hosting NSViews(因此您提供 CALayer 实例并使用setLayer: 设置它的 NSViews)显然可以包含子视图。为什么很明显?因为在 Apple 自己的 Cocoa Slides sample code project 中,您可以选中一个复选框,将 AssetCollectionView 从 layer-backed 切换到 layer-hosting:

- (void)setUsesQuartzCompositionBackground:(BOOL)flag {
    if (usesQuartzCompositionBackground != flag) {
        usesQuartzCompositionBackground = flag;

        /* We can display a Quartz Composition in a layer-backed view tree by 
           substituting our own QCCompositionLayer in place of the default automanaged 
           layer that AppKit would otherwise create for the view.  Eventually, hosting of 
           QCViews in a layer-backed view subtree may be made more automatic, rendering 
           this unnecessary.  To minimize visual glitches during the transition, 
           temporarily suspend window updates during the switch, and toggle layer-backed 
           view rendering temporarily off and back on again while we prepare and set the 
           layer.
        */
        [[self window] disableScreenUpdatesUntilFlush];
        [self setWantsLayer:NO];
        if (usesQuartzCompositionBackground) {
            QCCompositionLayer *qcLayer = [QCCompositionLayer compositionLayerWithFile:[[NSBundle mainBundle] pathForResource:@"Cells" ofType:@"qtz"]];
            [self setLayer:qcLayer];
        } else {
            [self setLayer:nil]; // Discard the QCCompositionLayer we were using, and let AppKit automatically create self's backing layer instead.
        }
        [self setWantsLayer:YES];
    }
}

在同一个AssetCollectionView 类中,为每个应显示的图像添加子视图:

- (AssetCollectionViewNode *)insertNodeForAssetAtIndex:(NSUInteger)index {
    Asset *asset = [[[self assetCollection] assets] objectAtIndex:index];
    AssetCollectionViewNode *node = [[AssetCollectionViewNode alloc] init];
    [node setAsset:asset];
    [[self animator] addSubview:[node rootView]];
    [nodes addObject:node];

    return [node autorelease];
}

当我构建并运行应用程序并使用它时,一切似乎都很好。

但是,Apple's NSView Class Reference for the setWantsLayer: method 中的内容是:

使用图层托管视图时,您不应依赖该视图 绘图,也不应将子视图添加到图层托管视图。

什么是真的?示例代码是否不正确,它的工作原理只是巧合?或者文件是假的(我怀疑)?还是因为子视图是通过animator代理添加的就OK了?

【问题讨论】:

    标签: cocoa core-animation calayer nsview


    【解决方案1】:

    我不知道这个问题的“正确”答案是什么。但我确实认为 CocoaSlides 示例在文档说你“不应该”做的范围内有效。在示例中,查看调用 insertNodeForAssetAtIndex: 方法的位置,您会发现它仅在视图被填充时发生,之前它曾经被分配一个层或已调用 setWantsLayer:就可以了。

    文档并没有说图层托管视图不能包含任何子视图,他们只是说您不能添加和子视图。在添加这些子视图的时间点,主视图尚未成为图层托管视图。通过为其分配手动创建的图层将其转换为图层托管视图后,不再添加子视图。

    因此,文档和这个特定示例之间确实没有矛盾。话虽如此,进一步探索这一点可能会很有趣,也许从一开始就打开 QC 背景层,例如通过在initWithFrame: 中粘贴[self setUsesQuartzCompositionBackground:YES];

    SPOLIER 警报: 它似乎工作得很好。显示的创建有点慢(所有 QC 动画都在进行中,这并不奇怪),但除此之外它还算顺利。

    【讨论】:

    【解决方案2】:

    当 AppKit 是“层托管”时,我们假设您可能(也可能没有)拥有 AppKit 不知道的整个层子树。

    如果您将子视图添加到图层托管视图,那么它可能不会以您想要的正确同级顺序出现。另外,我们有时会添加和删除它们,因此它可能会根据您何时调用 setLayer:、setWantsLayer: 或何时从父视图中添加或删除视图而改变。在 Lion(和之前)上,当视图从窗口(或超级视图)中移除时,我们会移除我们“拥有”的层(即:支持层)。

    可以添加子视图...如果您的兄弟层不是 NSView,它们在子层数组中的子层顺序可能不是确定性的。

    【讨论】:

    • 这在 2019 年仍然准确吗?
    • 应该是。如果他们更改了某个时间以使其无法正常工作,那么记录一个错误!
    【解决方案3】:

    Apple 对这段代码的一条评论:它被破坏了。

    当您第一次启动应用程序时,请注意漂亮的渐变背景。打开 QC,然后关闭。

    噗,没有渐变背景了。

    【讨论】:

      猜你喜欢
      • 2012-05-30
      • 2015-05-20
      • 1970-01-01
      • 2020-07-31
      • 2013-01-14
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多