top constraint ios objective-c autolayout nslayoutconstraint

ios - top - nslayoutconstraint swift 4



setNeedsLayout vs. setNeedsUpdateConstraints y layoutIfNeeded vs updateConstraintsIfNeeded (2)

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

  1. restricciones de actualización
  2. Vistas de diseño (aquí es donde obtenemos el cálculo de los marcos)
  3. monitor

Lo que no me queda totalmente claro es la diferencia interna entre -setNeedsLayout y -setNeedsUpdateConstraints . De Apple Docs:

setNeedsLayout

Llame a este método en el hilo principal de su aplicación cuando quiera ajustar el diseño de las subvistas de una vista. Este método toma nota de la solicitud y devuelve inmediatamente. Debido a que este método no fuerza una actualización inmediata, sino que espera el siguiente ciclo de actualización, puede usarlo para invalidar el diseño de varias vistas antes de que se actualice cualquiera de esas vistas. Este comportamiento le permite consolidar todas sus actualizaciones de diseño en un ciclo de actualización, que generalmente es mejor para el rendimiento.

setNeedsUpdateConstraints

Cuando una propiedad de su vista personalizada cambia de una manera que podría afectar las restricciones, puede llamar a este método para indicar que las restricciones deben actualizarse en algún momento en el futuro. El sistema llamará a updateConstraints como parte de su pase de diseño normal. Actualizar las restricciones de una sola vez, justo antes de que sean necesarias, garantiza que no vuelva a calcular las restricciones innecesariamente cuando se realicen múltiples cambios en su vista entre las pasadas de diseño.

Cuando quiero animar una vista después de modificar una restricción y animar los cambios, generalmente llamo 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 -setNeedsLayout lugar de -setNeedsUpdateConstraints todo funciona como se espera, pero si cambio -layoutIfNeeded con -updateConstraintsIfNeeded , la animación no sucederá.
He intentado llegar a mi propia conclusión:

  • -updateConstraintsIfNeeded solo actualiza las restricciones pero no obliga a que el diseño -updateConstraintsIfNeeded al proceso, por lo tanto, los cuadros originales aún se conservan
  • -setNeedsLayout también llama -updateContraints 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?


La respuesta por coverback es bastante correcta. Sin embargo, me gustaría añadir algunos detalles adicionales.

A continuación se muestra el diagrama de un ciclo UIView típico que explica otros comportamientos:

  1. Descubrí que si uso -setNeedsLayout lugar de -setNeedsUpdateConstraints todo funciona como se espera, pero si cambio -layoutIfNeeded con -updateConstraintsIfNeeded , la animación no sucederá.

updateConstraints normalmente no hace nada. Simplemente resuelve las restricciones, no las aplica hasta que se llama layoutSubviews . Así que la animación requiere una llamada a layoutSubviews .

  1. setNeedsLayout también llama al método -updateContraints

No, esto no es necesario. Si sus restricciones no se han modificado, UIView saltará la llamada a updateConstraints . setNeedsUpdateConstraint 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];


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

  • setNeedsUpdateConstraints se asegura de una futura llamada a updateConstraintsIfNeeded llama a updateConstraints .
  • setNeedsLayout se asegura de una futura llamada a layoutIfNeeded llamadas layoutSubviews .

Cuando se llama a updateConstraintsIfNeeded , también se llama a updateConstraintsIfNeeded , por lo que llamarlo manualmente rara vez es necesario en mi experiencia. De hecho, nunca lo he llamado, excepto al depurar diseños.

La actualización de restricciones usando setNeedsUpdateConstraints es bastante rara, objc.io, una lectura obligada sobre los autolayouts, 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 paso de actualización de restricción.

Además, en mi experiencia, nunca he tenido que invalidar las restricciones y no establecer setNeedsLayout en la siguiente línea del código, porque las nuevas restricciones casi setNeedsLayout un nuevo diseño.

Las reglas de oro son:

  • Si manipuló las restricciones directamente, llame a setNeedsLayout .
  • Si cambió algunas condiciones (como compensaciones o smth) que cambiarían las restricciones en su método de updateConstraints invalidado (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 alguna de las acciones anteriores para tener un efecto inmediato, por ejemplo, cuando necesite aprender una nueva altura de marco después de un pase de diseño, layoutIfNeeded con un layoutIfNeeded .

Además, en su código de animación, creo que setNeedsUpdateConstraints es necesario, ya que las restricciones se actualizan manualmente antes de la animación, y la animación solo re-establece la vista en función de las diferencias entre la antigua y la nueva.