Are NSViews supporting layers areas?

NSViews sliders (so the NSViews that you supply the CALayer instance and install it with setLayer: can obviously contain subviews. Why is it obvious? Because in Cocoa’s own code slide code project, you can select a checkbox that switches the AssetCollectionView to a layer that supports the hosting layer:

 - (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 backing layer instead. } [self setWantsLayer:YES]; } } 

In the same AssetCollectionView class AssetCollectionView for each image that should be displayed, sub-conclusions are added:

 - (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]; } 

When I create and run the application and play with it, everything seems beautiful.

However, in the Apple NSView Class Reference for the setWantsLayer: method setWantsLayer: it reads:

When using a layer-level view, you should not rely on the view for or add a subview to the layout level view.

What is true? Is the sample code incorrect and is it just a coincidence that it works? Or is the documentation false (which I doubt)? Or is this normal because subviews are added through the animator proxy?

+7
source share
3 answers

When AppKit is a “host on a layer”, we assume that you may (or not have) a whole layer subtree that AppKit is not aware of.

If you add a subview to a layer placed in the view, then it may not appear in the order you want. In addition, we sometimes add and remove them, so they can change depending on when you call setLayer :, setWantsLayer: or when a view is added or removed from the supervisor. On Lion (and earlier), we remove the layers that we “own” (that is, Maintain the layer) when the view is removed from the window (or supervisor).

It is possible to add subviews ... their child-sibling-order in an array of sublayers simply cannot be deterministic if you have sibling layers that are not NSViews.

+19
source

I do not know what this "correct" answer is. But I think the CocoaSlides example works as part of what the docs say you shouldn't do. In this example, look where the insertNodeForAssetAtIndex: method is insertNodeForAssetAtIndex: , and you will see that this only happens when the view is populated before it is ever assigned a layer or has setWantsLayer: called on it.

The documents do not say that the presentation placed at the level cannot contain any subheadings, they simply say that you cannot add and view them. At the moment when these subitems were added, the main view has not yet become a layout view at the layer level. After it was converted to a presentation of the placement level using the manually created layer assigned to it, no more additional objects were added.

Thus, there really is no contradiction between the documents and this particular example. It would be interesting to study this further, perhaps by including the QC background layer from the very beginning, for example, by inserting [self setUsesQuartzCompositionBackground:YES]; right inside initWithFrame:

SPOLIER WARNING: Everything seems to work fine. Creating a display is a bit slower (it’s not surprising that all this happens in QC animation), but in addition it swims smoothly.

+1
source

One comment about this code from Apple: it's busted.

When you first start the application, pay attention to a good gradient background. Turn on QC, then turn it off.

Poof, no more gradient background.

0
source

All Articles