2012-05-23 8 views
7

Las NSViews de alojamiento de capa (así NSViews para las que proporciona una instancia de CALayer y las configura con setLayer:) pueden contener obviamente subvistas. ¿Por qué obviamente? Debido a que en Apple propia Cocoa Slides sample code project, se puede comprobar una casilla de verificación que cambia la AssetCollectionView de ser respaldados por capa a ser la capa de alojamiento:¿Las NSView de alojamiento de capas tienen subvistas?

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

En la misma clase AssetCollectionView, se añaden subvistas para cada imagen que se debe mostrar:

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

Cuando construyo y ejecuto la aplicación y juego con ella, todo parece estar bien.

Sin embargo, en Apple's NSView Class Reference for the setWantsLayer: method se lee:

Cuando se utiliza una capa de vista de alojamiento no se debe confiar en la vista de dibujo, ni debe añadir subvistas a la vista de capas de alojamiento.

¿Qué es verdad? ¿El código de muestra es incorrecto y es solo una coincidencia que funciona? ¿O es la documentación falsa (que dudo)? ¿O está bien porque las subvistas se agregan a través del proxy animator?

Respuesta

19

Cuando AppKit es "alojamiento de capas" suponemos que puede (o no) tener un subárbol completo de capas que AppKit no conoce.

Si agrega una subvista a la vista de capa alojada, es posible que no aparezca en el orden de hermanos adecuado que desee. Además, a veces las agregamos y eliminamos, por lo que pueden cambiar dependiendo de cuándo llame a setLayer :, setWantsLayer: o cuando la vista se agregue o elimine de la supervista. En Lion (y antes) eliminamos las capas que "poseemos" (es decir, capa respaldada) cuando la vista se elimina de la ventana (o superview).

Está bien agregar subvistas ... el orden de sus hijos-hermanos en la matriz de subcapas podría no ser determinista si tiene capas hermanas que no son NSViews.

+0

Gracias ¡muchisimo! –

1

No sé cuál es la respuesta "correcta" para esto. Pero creo que el ejemplo de CocoaSlides funciona dentro de los límites de lo que los documentos dicen que "no debería" hacer. En el ejemplo, observe dónde se llama el método insertNodeForAssetAtIndex:, y verá que solo ocurre cuando la vista se completa, antes de siempre tiene asignada una capa o ha establecido setWantsLayer: invocado.

Los documentos no dicen que una vista alojada en capa no puede contener ninguna subvista, solo dicen que no puede agregar y las subvistas a una. En el momento en que se agregan esas subvistas, la vista principal aún no se ha convertido en una vista de alojamiento de capa. Una vez que se ha convertido en una vista de alojamiento de capas al asignársele una capa creada manualmente, no se agregarán más subvistas.

Así que realmente no hay contradicción entre los documentos y este ejemplo en particular. Una vez dicho esto, podría ser interesante explorar esto más a fondo, tal vez al encender la capa de fondo de CC desde el principio, p. pegando un [self setUsesQuartzCompositionBackground:YES]; dentro de initWithFrame:.

ALERTA DE SPOLIER: Parece que funciona bien. La creación de la pantalla es un poco más lenta (lo que no sorprende con toda la animación de control de calidad que se está llevando a cabo), pero aparte de eso, es una navegación fluida.

+0

Gracias, Jack! Interesante observación sobre "agregar" vs "tener ya" subvistas. Tal vez los documentos estén desactualizados, ya que también están relacionados con esta pregunta: http://stackoverflow.com/questions/10720062/are-layer-backed-nsview-siblings-allowed-to-overlap/10720422#10720422 –

0

Un comentario sobre este código de Apple: está reventado.

La primera vez que inicie la aplicación, tenga en cuenta el bonito fondo degradado. Encienda QC, luego apague.

Poof, no hay más fondo degradado.

Cuestiones relacionadas