Parece que con Xcode 8, viewDidLoad
todas las subvistas del controlador de vista tienen el mismo tamaño de 1000x1000. Lo extraño, pero bueno, viewDidLoad
nunca ha sido el mejor lugar para dimensionar correctamente las vistas.
¡Pero viewDidLayoutSubviews
es!
Y en mi proyecto actual, trato de imprimir el tamaño de un botón:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"%@", self.myButton);
}
¡El registro muestra un tamaño de (1000x1000) para myButton! Luego, si inicio sesión en un botón, haga clic, por ejemplo, el registro muestra un tamaño normal.
Estoy usando diseño automático.
¿Es un error?
ios
autolayout
ios10
xcode8
Martín
fuente
fuente
(0, 0, 1000, 1000)
inicialización enlazada es la nueva forma en que Xcode instancia las vistas de IB. Antes de Xcode8, las vistas se creaban con su tamaño configurado en el xib y luego se cambiaban de tamaño según la pantalla justo después. Pero ahora, no hay un tamaño configurado en el documento IB ya que el tamaño depende de la selección de su dispositivo (en la parte inferior de la pantalla). Entonces, la pregunta real es: ¿existe un lugar confiable donde se pueda verificar el tamaño final de las vistas?Respuestas:
Ahora, Interface Builder permite al usuario cambiar dinámicamente el tamaño de cada controlador de vista en el guión gráfico, para simular el tamaño de un determinado dispositivo.
Antes de esta funcionalidad, el usuario debe configurar manualmente el tamaño de cada controlador de vista. Entonces, el controlador de vista se guardó con un cierto tamaño, que se usó
initWithCoder
para establecer el marco inicial.Ahora, parece que
initWithCoder
no use el tamaño definido en el guión gráfico y defina un tamaño de 1000x1000 px para la vista del controlador de vista y todas sus subvistas.Esto no es un problema, porque las vistas siempre deben usar cualquiera de estas soluciones de diseño:
autolayout, y todas las restricciones diseñarán correctamente sus vistas
autoresizingMask, que diseñará cada vista que no tenga ninguna restricción adjunta ( tenga en cuenta que el diseño automático y las restricciones de margen ahora son compatibles en la misma vista \ o /! )
Pero esto es un problema para todas las cosas de diseño relacionadas con la capa de vista
cornerRadius
, ya que ni el diseño automático ni la máscara de tamaño automático se aplican a las propiedades de la capa.Para responder a este problema, la forma más común es utilizarlo
viewDidLayoutSubviews
si está en el controlador olayoutSubview
si está en una vista. En este punto (no olvide llamar a sussuper
métodos relativos), ¡está bastante seguro de que se ha hecho todo el diseño!¿Bastante seguro? Hum ... no del todo, he comentado, y es por eso que hice esta pregunta, en algunos casos la vista todavía tiene su tamaño de 1000x1000 en este método. Creo que no hay respuesta a mi propia pregunta. Para dar la máxima información al respecto:
1- ¡ocurre solo al colocar celdas! En las subclases
UITableViewCell
&UICollectionViewCell
,layoutSubview
no se llamará después de que las subvistas estén correctamente distribuidas.2- Como comentó @EugenDimboiu (por favor, vote a favor de su respuesta si es útil para usted), llamar
[myView layoutIfNeeded]
a la subvista no diseñada la distribuirá correctamente justo a tiempo.3- En mi opinión, esto es definitivamente un error. Lo envié al radar (id 28562874).
PD: no soy nativo de inglés, así que siéntete libre de editar mi publicación si se debe corregir mi gramática;)
PS2: Si tiene una solución mejor, no dude en escribir otra respuesta. Moveré la respuesta aceptada.
fuente
UIStackView
interior de unUICollectionViewCell
no devolvía la altura correcta duranteviewDidLayoutSubviews
. LlamarlayoutIfNeeded
inmediatamente rectificó el problema.¿Estás usando esquinas redondeadas para tu botón? Intente llamar
layoutIfNeeded()
antes.fuente
Solución: envolver todo el interior
viewDidLayoutSubviews
enDispatchQueue.main.async
.fuente
-viewDidLoad
... una solución tan extrañaSé que esta no era su pregunta exacta, pero me encontré con un problema similar en el que, en la actualización, algunas de mis vistas se estropearon a pesar de tener el tamaño de marco correcto en viewDidLayoutSubviews. Según las notas de la versión de iOS 10:
Esencialmente, no puede llamar a layoutIfNeeded en un objeto secundario de la Vista si está utilizando translatesAutoresizingMaskIntoConstraints; ahora, la llamada a layoutIfNeeded debe estar en la superView, y aún puede llamar a esto en viewDidLayoutSubviews.
fuente
Si los marcos no son correctos en layoutSubViews (que no lo son), puede enviar async un poco de código en el hilo principal. Esto le da al sistema algo de tiempo para hacer el diseño. Cuando se ejecuta el bloque que envías, los marcos tienen sus tamaños adecuados.
fuente
Esto solucionó el problema (ridículamente molesto) para mí:
Editar / Nota: Esto es para un ViewController de pantalla completa.
fuente
[super viewDidLayoutSubviews];
a este método debido a muchas cosas de diseño automático realizadas por la vista en síUIView
s. Pero si debe realizar un cálculo especial en un determinado marco de vista, la respuesta de Eugen funciona: invocarlolayoutIfNeeded
. Tengo la sensación de que esta no es la mejor solución, pero todavía no he encontrado ninguna mejor.En realidad,
viewDidLayoutSubviews
tampoco es el mejor lugar para establecer el marco de su vista. Por lo que tengo entendido, a partir de ahora, el único lugar en el que debería hacerse es ellayoutSubviews
método en el código de la vista real. Ojalá no estuviera en lo cierto, ¡que alguien me corrija si no es verdad!fuente
viewDidLayoutSubviews
es bastante ambigua. La segunda oración de "discusiones" contradice de alguna manera la última. developer.apple.com/reference/uikit/uiviewcontroller/…Ya informé este problema a Apple, este problema existe desde hace mucho tiempo, cuando está inicializando UIViewController desde Xib, pero encontré una solución bastante buena. Además de eso, encontré ese problema en algunos casos cuando layoutIfNeeded en UICollectionView y UITableView cuando la fuente de datos no está configurada en el momento inicial, y también necesitaba swizzle.
Envío una vez extensión:
Extensión Swizzle:
fuente
Mi problema se resolvió cambiando el uso de
a
Entonces, de Did a Will
Super raro
fuente
Mejor solución para mí.
Utilizando
fuente
Anular layoutSublayers (de la capa: CALayer) en lugar de layoutSubviews en la subvista de celda para tener los marcos correctos
fuente
Si necesita hacer algo basado en el marco de su vista, anule layoutSubviews y llame a layoutIfNeeded
Tuve el problema con viewDidLayoutSubviews que devolvía el marco incorrecto para mi vista, por lo que necesitaba agregar un degradado. Y solo layoutIfNeeded hizo lo correcto :)
fuente
Según la nueva actualización en ios, esto es en realidad un error, pero podemos reducirlo usando -
Si está utilizando xib con diseño automático en su proyecto, solo tiene que actualizar el marco en la configuración de diseño automático, busque la imagen para esto.
fuente