setNeedsLayout vs setNeedsUpdateConstraints y layoutIfNeeded vs updateConstraintsIfNeeded


Sé que la cadena de diseño automático consiste básicamente en 3 procesos diferentes.

  1. actualización de restricciones
  2. vistas de diseño (aquí es donde obtenemos el cálculo de fotogramas)
  3. 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?

Author: Honey, 2013-12-16

2 answers

Sus conclusiones son correctas. El esquema básico es:

  • setNeedsUpdateConstraints se asegura de que una llamada futura a updateConstraintsIfNeeded llame a updateConstraints.
  • setNeedsLayout se asegura de que una llamada futura a layoutIfNeeded llame a layoutSubviews.

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étodoupdateConstraints anulado (una forma recomendada de cambiar las restricciones, por cierto), llame a setNeedsUpdateConstraints, 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.

 242
Author: coverback,
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 Ciclo de vida de UIView

  1. 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.

  1. 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];
 72
Author: Kunal Balani,
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