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 los marcos)
- monitor
Lo que no está totalmente claro para mí es la diferencia interna entre -setNeedsLayouty -setNeedsUpdateConstraints. De Apple Docs:
Llame a este método en el hilo principal de su aplicación cuando desee ajustar el diseño de las subvistas de una vista. Este método toma nota de la solicitud y regresa de inmediato. Debido a que este método no fuerza una actualización inmediata, sino que espera el próximo ciclo de actualización, puede usarlo para invalidar el diseño de varias vistas antes de que cualquiera de esas vistas se actualice. Este comportamiento le permite consolidar todas sus actualizaciones de diseño en un ciclo de actualización, que generalmente es mejor para el rendimiento.
Cuando una propiedad de su vista personalizada cambia de una manera que afectaría las restricciones, puede llamar a este método para indicar que las restricciones deben actualizarse en algún momento en el futuro. El sistema luego llamará a updateConstraints como parte de su pase de diseño normal. La actualización de todas las restricciones de una vez, justo antes de que sean necesarias, garantiza que no recalcule innecesariamente las restricciones cuando se realizan múltiples cambios en su vista entre los 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];
Descubrí que si uso en -setNeedsLayoutlugar de que -setNeedsUpdateConstraintstodo funcione como se esperaba, pero si cambio -layoutIfNeededcon -updateConstraintsIfNeeded, la animación no sucederá.
Intenté llegar a mi propia conclusión:
-updateConstraintsIfNeededsolo actualiza las restricciones pero no obliga al diseño a entrar en el proceso, por lo tanto, los marcos originales aún se conserva-setNeedsLayouttambién llama-updateContraintsmétodo
Entonces, ¿cuándo está bien usar uno en lugar del otro? y sobre los métodos de diseño, ¿debo llamarlos en la vista que tiene un cambio en una restricción o en la vista principal?

Respuestas:
Tus conclusiones son correctas. El esquema básico es:
setNeedsUpdateConstraintsse asegura de una futura llamada aupdateConstraintsIfNeededllamadasupdateConstraints.setNeedsLayoutse asegura de una futura llamada alayoutIfNeededllamadaslayoutSubviews.Cuando
layoutSubviewsse llama, también llamaupdateConstraintsIfNeeded, por lo que en mi experiencia rara vez se necesita llamarlo manualmente. De hecho, nunca lo he llamado, excepto al depurar diseños.setNeedsUpdateConstraintsTambién es bastante raro actualizar las restricciones usando , objc.io, una lectura obligada sobre autolayouts, dice :Además, en mi experiencia, nunca he tenido que invalidar restricciones, y no establecerlas
setNeedsLayouten la siguiente línea del código, porque las nuevas restricciones están pidiendo un nuevo diseño.Las reglas generales son:
setNeedsLayout.updateConstraintsmétodo (un método recomendado a las restricciones de cambio, por cierto), llamadasetNeedsUpdateConstraints, y la mayoría de las veces,setNeedsLayoutdespués de eso.layoutIfNeeded.Además, en su código de animación, creo que no
setNeedsUpdateConstraintses necesario, ya que las restricciones se actualizan antes de la animación manualmente, y la animación solo vuelve a mostrar la vista en función de las diferencias entre las antiguas y las nuevas.fuente
setNeedsLayout.setNeedsLayoutse asegura delayoutSubviewsque se llamará en el próximo ciclo de actualización, pero ¿quizás esto no tenga nada que verlayoutIfNeeded?layoutSubviewste llamará automáticamente, no es necesario llamarsetNeedsLayoutlayoutSubviews, por lo que no es necesario hacerlo manualmente. Sin embargo, debe llamarlayoutIfNeededsi necesita que los cambios surtan efecto de inmediato en lugar del próximo ciclo de diseñoLa respuesta del coverback es bastante correcta. Sin embargo, me gustaría agregar algunos detalles adicionales.
A continuación se muestra el diagrama de un ciclo típico de UIView que explica otros comportamientos:
-setNeedsLayoutlugar de que-setNeedsUpdateConstraintstodo funcione como se esperaba, pero si cambio-layoutIfNeededcon-updateConstraintsIfNeeded, la animación no sucederá.updateConstraintsnormalmente no hace nada. Simplemente resuelve las restricciones, no las aplica hasta quelayoutSubviewsse llama. Entonces la animación requiere una llamada alayoutSubviews.No, esto no es necesario. Si sus restricciones no se han modificado, UIView se saltará la llamada
updateConstraints. Debe llamar explícitamentesetNeedsUpdateConstraintpara modificar las restricciones en el proceso.Para llamar
updateConstraintsnecesita hacer lo siguiente:fuente