Tengo una vista personalizada que no recibe 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 correctamente distribuidas. Si desactivo la barra de estado de la llamada, la subvista layoutSubviews
no se llama en absoluto, aunque la vista principal anima su cambio de tamaño.
¿Bajo qué circunstancias se layoutSubviews
llama realmente?
He autoresizesSubviews
configurado NO
para mi vista personalizada. Y en Interface Builder tengo los puntales superior e inferior y el conjunto de flechas verticales.
Otra parte del rompecabezas es que la ventana debe hacerse clave:
[window makeKeyAndVisible];
de lo contrario, las subvistas no se redimensionan automáticamente.
fuente
layoutSubviews
. ¿initWithFrame:
CausalayoutSubviews
ser llamado?view1.1
se llamalayoutSubviews
deview1
y luegolayoutSubviews
deview1.1
. Esta llamada no se propaga indefinidamente a las supervistas,view1.1.1
solo se llamalayoutSubviews
a las llamadasview1.1
yview1.1.1
. Simplemente moverse sin cambiar su tamaño no llamalayoutSubviews
a ninguno de ellos.view1.2
aview1
,layoutSubviews
deview1.2
yview1
se llama, perolayoutSubviews
deview1.1
no se llama. (view1.1
yview1.2
son subvistas deview1
). Es decir, no todas las subvistas de la vista de destino se denominanlayoutSubviews
método .Partiendo de la respuesta anterior de @BadPirate, experimenté un poco más y obtuve algunas aclaraciones / correcciones. Descubrí que
layoutSubviews:
se invocará en una vista si y solo si:Algunos detalles relevantes:
layoutSubviews:
se llama cada vez que se desplaza un UIScrollView, ya que realiza el desplazamiento cambiando el origen de sus límites.layoutSubviews:
cuando la vista finalmente se agregue a una jerarquía de vistas .setNeedsLayout
, lo que establece / levanta una bandera. Cada iteración del ciclo de ejecución, para todas las vistas en la jerarquía de vistas , se marca este indicador. Para cada vista donde se encuentra la bandera levantada,layoutSubviews:
se le llama y se restablece la bandera. Las vistas más arriba en la jerarquía se verificarán / llamarán primero.fuente
https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1
fuente
Algunos de los puntos en la respuesta de BadPirate son solo parcialmente ciertos:
Por
addSubView
puntoDepende de la máscara de tamaño automático de la vista (vista de destino). Si tiene la máscara de tamaño automático activada, se llamará a layoutSubview en cada una
addSubview
. Si no tiene máscara de tamaño automático, se llamará a layoutSubview solo cuando cambie el tamaño del marco de la vista (Vista de destino).Ejemplo: si creó UIView mediante programación (no tiene máscara de tamaño automático de forma predeterminada), LayoutSubview solo se llamará cuando el marco de UIView no cambie en todos
addSubview
.Es a través de esta técnica que el rendimiento de la aplicación también aumenta.
Para el punto de rotación del dispositivo
Esto puede ser cierto solo cuando su VC está en la jerarquía de VC (raíz en
window.rootViewController
), bueno, este es el caso más común. En iOS 5, si crea un VC, pero no se agrega a ningún otro VC, entonces este VC no se notará cuando el dispositivo gire. Por lo tanto, su vista no se notará llamando a layoutSubviews.fuente
Rastreé la solución hasta la insistencia de Interface Builder de que los resortes no se pueden cambiar en una vista que tiene los elementos de pantalla simulados activados (barra de estado, etc.). Dado que los resortes estaban fuera de la vista principal, esa vista no podía cambiar de tamaño y, por lo tanto, se desplazó hacia abajo en su totalidad cuando apareció la barra de llamada.
Desactivar las características simuladas, luego cambiar el tamaño de la vista y configurar los resortes correctamente hizo que se produjera la animación y se llamara a mi método.
Un problema adicional en la depuración es que el simulador cierra la aplicación cuando el estado de la llamada se alterna a través del menú. Salga de la aplicación = sin depurador.
fuente
llamando
[self.view setNeedsLayout];
a viewController hace que llame a viewDidLayoutSubviewsfuente
has mirado layoutIfNeeded?
El fragmento de documentación está debajo. ¿Funciona la animación si llamas a este método explícitamente durante la animación?
layoutIfNeeded Presenta las subvistas si es necesario.
Discusión Use este método para forzar el diseño de las subvistas antes de dibujar.
Disponibilidad Disponible en iPhone OS 2.0 y posterior.
fuente
Al migrar una aplicación OpenGL de SDK 3 a 4, ya no se llamaba a layoutSubviews. Después de muchas pruebas y errores, finalmente abrí MainWindow.xib, seleccioné el objeto Window, en el inspector elegí la pestaña Atributos de ventana (más a la izquierda) y marqué "Visible en el lanzamiento". Parece que en el SDK 3 todavía solía causar una llamada a layoutSubViews, pero no en 4.
Se acabaron 6 horas de frustración.
fuente
Un caso bastante oscuro pero potencialmente importante cuando
layoutSubviews
nunca se llama es:fuente