2010-09-24 16 views
15

No encuentro una respuesta decente para explicarme la diferencia entre estas 2 funciones. ¿Cuándo se llama a cada uno y cómo se diferencia uno del otro?drawrect Vs layoutsubviews - NSView - Cocoa touch

por ejemplo, ¿no puedo simplemente diseñar mis vistas dentro de drawrect?

Gracias

Respuesta

56

-layoutSubviews se llama desde -layoutIfNeeded si el "diseño necesitaba" se estableció la bandera (usando -setNeedsLayout, o automáticamente cuando la vista limita los cambios). Úselo para posicionar su vista [EDITAR: Úselo para el posicionamiento subvistas].

-drawRect: se llama desde -displayIfNeeded si la "pantalla sea necesario" bandera se establece (utilizando -setNeedsDisplay, o automáticamente si se establece view.contentMode = UIViewContentModeRedraw).

Ambos -layoutIfNeeded y -displayIfNeeded son llamados automáticamente por UIKit/CoreAnimation antes de que las cosas se dibujen en la pantalla; rara vez necesita llamarlos directamente.

usted puede colocar su subvistas en -drawRect: (incluso se puede añadir subvistas!), Pero esto es poco prudente:

  • Por defecto, -setNeedsDisplay no se busca automáticamente en un cambio de límites.
  • La implementación de -drawRect: reduce el rendimiento (UIKit/CoreAnimation tiene que crear un contexto de gráficos respaldado por mapa de bits para usted); solo hazlo si necesitas realizar un dibujo personalizado.
  • Necesita volver a dibujar la vista en -drawRect:. El dibujo es caro Mover vistas es barato.
  • UIKit/CoreAnimation probablemente haga un pase de disposición seguido de un pase de dibujo. CoreAnimation puede usar información de diseño para decidir qué vistas necesitan dibujo (por ejemplo, podría ignorar vistas oscurecidas por subvistas opacas, vistas fuera de la pantalla o subvistas fuera de los límites de una vista clipsToBounds = YES, o solo podría dibujar un subtítulo de un vista grande). Si mueve vistas durante el pase de dibujo, es posible que CoreAnimation no las dibuje correctamente.

EDIT: Y algo más de detalle cuando estoy despierto:

¿Cuál es la diferencia entre "pantalla" y "dibujar"? La visualización se realiza por -[CALayer display]; la implementación por defecto es (aproximadamente)

  • Si el delegado de la capa responde a -displayLayer:, llame [self.delegate displayLayer:self].-displayLayer: se supone que establecer layer.content a (por ejemplo) un CGImage,
  • De lo contrario, si el delegado de la capa responde a -drawLayer:inContext:, estableció un marco de mapa de bits con respaldo, llame [self.delegate drawLayer:self inContext:context], y guardar el resultado en layer.content (la salida es en realidad un CABackingStore , que presumiblemente es una API privada)
  • De lo contrario, no cambie layer.content.

la vista es el delegado de la capa, por lo que puede poner en práctica -[MyView displayLayer:] lugar, y hacer cosas interesantes, como

  • self.layer.contents = (id)([UIImage imageNamed:@"foo"].CGImage) (que es más o menos lo que hace UIImageView)
  • Un no-op, para evitar cualquier "dibujo". Esto podría ser útil si ha subclasificado, p. UIToolbar y quiero darle un fondo transparente. (Esto también evita la creación de CGContext/CABackingStore).
  • Mueva las subvistas sin penalización de rendimiento (pero aún así no es una buena idea por las razones anteriores).
+0

Gran respuesta. ¡Gracias! – Idan

-2

Tal vez no tengo todas las respuestas, pero puedo decir que eso: - layoutSubviews se llama cuando el marco de vista se cambia - drawRect se llama cuando se llama setNeedDisplay

La mayoría de las veces no usarás layoutSubviews.

puede haber otros casos, pero que podría dar una primera pieza de respuesta ^^

Buena suerte

+0

Proporcione más detalles sobre su afirmación de que "la mayoría de las veces no usará layoutSubviews". –

Cuestiones relacionadas