2012-05-23 120 views
7

图层托管NSViews(因此您提供CALayer实例并将其设置为setLayer:的NSViews)显然可以包含子视图。为什么显然?因为在苹果自己的Cocoa Slides sample code project,您可以检查被层为后盾,以被层托管切换AssetCollectionView复选框:图层托管NSView允许有子视图吗?

- (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记载:

当使用一个层托管视图,你不应该依赖于 图纸来看,也不应该添加子视图层托管视图。

什么是真的?示例代码是否有误,它只是巧合而已?或者是文档错误(我怀疑)?还是可以的,因为子视图是通过动画代理添加的?

回答

19

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

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

可以添加子视图...如果您的兄弟图层不是NSView,则子图层数组中的子级兄弟顺序可能不是确定性的。关于苹果这个代码

+0

谢谢非常非常! –

1

我不知道什么是“正确”的答案。但我确实认为CocoaSlides示例在文档所说的“不应该”做的范围内工作。在该示例中,查看insertNodeForAssetAtIndex:方法的调用方式,您将看到它仅在填充视图时发生,之前被分配了一个图层或具有setWantsLayer:对其调用。

文档没有说层次托管的视图不能包含任何子视图,他们只是说,你不能添加和子视图到一个。在添加子视图的时候,主视图还没有成为图层托管视图。在通过手动创建的图层分配给图层托管视图后,不再添加子视图。

所以文档和这个特定的例子之间确实没有矛盾。也就是说,进一步探索这一点可能会很有趣,可能是从一开始就打开QC背景层,例如,通过坚持内initWithFrame:[self setUsesQuartzCompositionBackground:YES];

SPOLIER ALERT: 它似乎工作得很好。显示屏的创建速度稍慢(对于所有QC动画而言并不令人意外),但除此之外,它是顺畅的航行。

+0

谢谢,杰克!关于“添加”与“已有”子视图有趣的观察。也许文档是过时的,因为他们是这个问题太:http://stackoverflow.com/questions/10720062/are-layer-backed-nsview-siblings-allowed-to-overlap/10720422#10720422 –

0

一个评论:它打掉。

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

噗,没有更多的渐变背景。