-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).
Gran respuesta. ¡Gracias! – Idan