¿Cuándo se llama a layoutSubviews?
-
05-09-2019 - |
Pregunta
Tengo una vista personalizada que no aparece. layoutSubview
mensajes durante la animación.
Tengo una vista que llena la pantalla.Tiene una subvista personalizada en la parte inferior de la pantalla que cambia de tamaño correctamente en Interface Builder si cambio la altura de la barra de navegación. layoutSubviews
Se llama cuando se crea la vista, pero nunca más.Mis subvistas están diseñadas correctamente.Si desactivo la barra de estado de la llamada entrante, la subvista layoutSubviews
no se llama en absoluto, aunque la vista principal anima su cambio de tamaño.
¿En qué circunstancias es layoutSubviews
realmente llamado?
Tengo autoresizesSubviews
ajustado a NO
para mi vista personalizada.Y en Interface Builder tengo configurados los puntales superior e inferior y la flecha vertical.
Otra parte del rompecabezas es que la ventana debe ser clave:
[window makeKeyAndVisible];
De lo contrario, las subvistas no cambian de tamaño automáticamente.
Solución 5
Rastreé la solución a la insistencia de Interface Builder que los muelles no se pueden cambiar en una vista que tienen los elementos de la pantalla simuladas activadas (barra de estado, etc.). Desde los muelles estaban fuera de la vista principal, ese punto de vista no podía cambiar el tamaño y por lo tanto se ha desplazado hacia abajo en su totalidad cuando la barra de llamada entrante apareció.
En cuanto las características simuladas, luego cambiar el tamaño de la vista y el establecimiento de los resortes correctamente causó la animación a ocurrir y mi método a ser llamado.
Un problema adicional en la depuración de esto es que el simulador se cierra la aplicación cuando el estado de la llamada entrante se activa a través del menú. Dejar de aplicación = no depurador.
Otros consejos
Tenía una pregunta similar, pero no estaba satisfecho con la respuesta (ni con ninguna que pudiera encontrar en la red), así que lo intenté en la práctica y esto es lo que obtuve:
init
no causalayoutSubviews
para ser llamado (duh)addSubview:
causaslayoutSubviews
para ser llamado a la vista que se está agregando, la vista que se está agregando añadido a (vista de destino), y todos los subvistas del destino- vista
setFrame
llama inteligentementelayoutSubviews
en La vista que solo tiene su marco establecido Si el parámetro de tamaño del fotograma es diferente - desplazamiento de UIScrollView
Causas
layoutSubviews
para ser llamado scrollView, y su supervista - rotar un dispositivo solo llama
layoutSubview
En la vista principal (la vista principal (la viewControllers primario que responde vista) - Cambiar el tamaño de una vista llamará
layoutSubviews
en su supervisión
Mis resultados - http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-call/
Sobre la base de la respuesta anterior por @BadPirate, experimenté un poco más y se acercó con algunas aclaraciones / correcciones. He descubierto que layoutSubviews:
se llamará en una vista si y sólo si:
- Sus propios límites (no enmarcar) cambiaron.
- Los límites de uno de sus directos subvistas cambiaron.
- Se añade una subvista a la vista o elimina de la vista.
Algunos detalles pertinentes:
- Los límites son considerados sólo cambia si el nuevo valor es diferente, que incluye un origen diferente . Tenga en cuenta específicamente que es la razón por
layoutSubviews:
es llamada cuando un UIScrollView pergaminos, ya que realiza el desplazamiento cambiando el origen de sus límites. - cambiar el marco de sólo cambiará los límites si el tamaño ha cambiado, ya que esto es lo único que se propagó a la propiedad límites.
- Un cambio en los límites de la opinión de que todavía no está en una jerarquía de vistas resultará en una llamada a
layoutSubviews:
cuando la vista se añadió finalmente a una jerarquía de vistas . - Y simplemente para la corrección: estos disparadores no lo hacen directamente llamar layoutSubviews, sino más bien llamar
setNeedsLayout
, que establece / levanta una bandera. Cada iteración del bucle de ejecución, para todos los puntos de vista en la jerarquía de vistas , se activa esta bandera. Para cada punto de vista donde se encuentra levantó la bandera,layoutSubviews:
se llama en ella y la bandera se pone a cero. Vistas más arriba en la jerarquía serán comprobados / llamada en primer lugar.
Los cambios de configuración pueden ocurrir cuando cualquiera de los siguientes eventos ocurre en una vista:
a. El tamaño de los cambios de límites del rectángulo de una vista.
si. Un cambio de orientación de interfaz se produce, lo que normalmente provoca un cambio en la vista raíz límites del rectángulo.
C. El conjunto de subcapas Core Animation asociados con cambios en la capa de la vista y requiere el diseño.
re. Su diseño fuerzas de aplicación que se produzca llamando al métodosetNeedsLayout
olayoutIfNeeded
de una vista.
mi. Su fuerzas de aplicación la disposición llamando al métodosetNeedsLayout
del objeto de capa subyacente de la vista.
Algunos de los puntos en de BadPirate respuesta son sólo parcialmente cierto:
-
Para el punto
addSubView
addSubview
causa layoutSubviews para ser llamados en la vista que se añade, la vista está siendo añadido a (vista de destino), y todos los subvistas del objetivo.Depende (vista de destino) autoresize máscara de la vista. Si tiene autoresize máscara, layoutSubview será llamado en cada
addSubview
. Si no tiene máscara autoresize continuación layoutSubview se llamará sólo cuando (destino) Ver los cambios de tamaño de marco de la vista.Ejemplo: si ha creado UIView programación (no tiene máscara autoresize por defecto), LayoutSubview se llama sólo cuando el marco UIView no cambia en cada
.addSubview
Es a través de esta técnica que el rendimiento de la aplicación también se incrementa.
-
En el punto de rotación dispositivo
Rotación de un dispositivo de sólo llama layoutSubview en la vista padre (la respuesta de vista principal de viewController)
Esto puede ser cierto sólo cuando el VC es en la jerarquía de VC (raíz en
window.rootViewController
), así que esto es el caso más común. En iOS 5, si crea un VC, pero no se ha agregado a cualquier otra VC, VC entonces este no obtendría ninguna notó cuando rote dispositivo. Por lo tanto, su opinión no sería llamar la atención llamando layoutSubviews.
llamadas
[self.view setNeedsLayout];
en viewController hace que sea para llamar viewDidLayoutSubviews
¿Has mirado en layoutIfNeeded?
El fragmento de la documentación se encuentra por debajo. ¿El trabajo de animación si se llama a este método de forma explícita durante la animación?
layoutIfNeeded Expone la subvistas si es necesario.
- (void)layoutIfNeeded
discusión Utilizar este método para obligar a la disposición de subvistas antes de dibujar.
Disponibilidad Disponible en el iPhone OS 2.0 y posterior.
Al migrar una aplicación OpenGL SDK de 3 a 4, layoutSubviews no fue llamado nunca más. Después de mucho ensayo y error, finalmente abrí MainWindow.xib, seleccionado el objeto de ventana, en el inspector eligió Ventana ficha Atributos (más a la izquierda) y se comprueba "visible en el lanzamiento". Parece que en SDK 3 que todavía se utiliza para causar una llamada layoutSubViews, pero no en 4.
6 horas de frustración ponen a su fin.
Un caso bastante oscura, pero potencialmente importante cuando layoutSubviews
nunca se ha llamado es:
import UIKit
class View: UIView {
override class var layerClass: AnyClass { return Layer.self }
class Layer: CALayer {
override func layoutSublayers() {
// if we don't call super.layoutSublayers()...
print(type(of: self), #function)
}
}
override func layoutSubviews() {
// ... this method never gets called by the OS!
print(type(of: self), #function)
}
}
let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))