setNeedsLayout vs setNeedsUpdateConstraints y layoutIfNeeded vs updateConstraintsIfNeeded
Sé que la cadena de diseño automático consiste básicamente en 3 procesos diferentes.
- actualización de restricciones
- vistas de diseño (aquí es donde obtenemos el cálculo de fotogramas)
- mostrar
Lo que no está totalmente claro para mí es la diferencia interna entre -setNeedsLayout
y -setNeedsUpdateConstraints
. Desde Apple Docs:
SetNeedsLayout
Llama a este método en el hilo principal de tu aplicación cuando quieras ajustar el diseño de subviews de una vista. Este método hace una nota de la solicitud y devoluciones inmediatamente. Porque este método no forzar una actualización inmediata, pero en su lugar espera la siguiente actualización ciclo, puede usarlo para invalidar el diseño de varias vistas antes de que se actualice cualquiera de esas vistas. Este comportamiento le permite consolide todas las actualizaciones de su diseño en un ciclo de actualización, que es por lo general mejor para el rendimiento.
Restricciones de la actualización
Cuando una propiedad de su vista personalizada cambia de una manera que afectaría restricciones, puede llamar a este método para indicar que las restricciones necesita ser actualizado en algún momento en el futuro. El sistema entonces llame a updateConstraints como parte de su pase de diseño normal. Actualizar restricciones todos a la vez justo antes de que sean necesarios asegura que usted no recalcular innecesariamente las restricciones cuando los cambios múltiples son hecho a su vista entre pases de diseño.
Cuando quiero animar una vista después de modificar una restricción y animar los cambios que suelo llamar por ejemplo:
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
He descubierto que si utilizo -setNeedsLayout
en lugar de -setNeedsUpdateConstraints
todo funciona como se esperaba, pero si cambio -layoutIfNeeded
con -updateConstraintsIfNeeded
, la animación no sucederá.
He tratado de hacer mi propia conclusión:
-
-updateConstraintsIfNeeded
solo actualiza las restricciones, pero no obliga a que el diseño entre el proceso, por lo tanto, los marcos originales todavía se conservan -
-setNeedsLayout
también llama al método-updateContraints
Entonces, ¿cuándo está bien usar uno en lugar del otro? y sobre los métodos de diseño, ¿necesito llamarlos en la vista que tiene un cambio en una restricción o en la vista principal?
2 answers
Sus conclusiones son correctas. El esquema básico es:
-
setNeedsUpdateConstraints
se asegura de que una llamada futura aupdateConstraintsIfNeeded
llame aupdateConstraints
. -
setNeedsLayout
se asegura de que una llamada futura alayoutIfNeeded
llame alayoutSubviews
.
Cuando se llama layoutSubviews
, también llama updateConstraintsIfNeeded
, por lo que llamarlo manualmente rara vez es necesario en mi experiencia. De hecho, nunca lo he llamado excepto al depurar diseños.
Actualizar restricciones usando setNeedsUpdateConstraints
también es bastante raro, objc. io–a debe leer sobre autodiagnóstico-dice :
Si algo cambia más adelante que invalida una de sus restricciones, debe eliminar la restricción inmediatamente y llamar a setNeedsUpdateConstraints. De hecho, ese es el único caso en el que debería tener que activar un pase de actualización de restricción.
Además, en mi experiencia, nunca he tenido que invalidar restricciones, y no establecer el setNeedsLayout
en la siguiente línea del código, porque las nuevas restricciones más o menos están pidiendo un nuevo diseño.
Las reglas de oro son:
- Si ha manipulado restricciones directamente, llame a
setNeedsLayout
. - Si ha cambiado algunas condiciones (como compensaciones o smth) que cambiarían las restricciones en su método
updateConstraints
anulado (una forma recomendada de cambiar las restricciones, por cierto), llame asetNeedsUpdateConstraints
, y la mayoría de las veces,setNeedsLayout
después de eso. - Si necesita que cualquiera de las acciones anteriores tenga efecto inmediato, por ejemplo, cuando necesita aprender una nueva altura de fotograma después de un layout pass-añádelo con un
layoutIfNeeded
.
Además, en su código de animación, creo que setNeedsUpdateConstraints
no es necesario, ya que las restricciones se actualizan antes de la animación manualmente, y la animación solo re-establece la vista en función de las diferencias entre las antiguas y las nuevas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-27 15:44:40
La respuesta de coverback es bastante correcta . Sin embargo, me gustaría añadir algunos detalles adicionales.
A continuación se muestra el diagrama de un ciclo típico de UIView que explica otros comportamientos
- He descubierto que si uso-setNeedsLayout en lugar de-setNeedsUpdateConstraints todo funciona como se esperaba, pero si cambio-layoutIfNeeded con-updateConstraintsIfNeeded, la animación no sucederá.
updateConstraints
normalmente no lo hace nada. Simplemente resuelve restricciones no las aplica hasta que se llama layoutSubviews
. Así que la animación requiere una llamada a layoutSubviews
.
- También llama a setNeedsLayout-método updateContraints
No, esto no es necesario. Si sus restricciones no han sido modificadas, UIView saltará la llamada a updateConstraints
. Necesita llamar explícitamente a setNeedsUpdateConstraint
para modificar las restricciones en el proceso.
Para llamar a updateConstraints
necesitas hacer lo siguiente:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-22 17:12:15