Pregunta ¿Cuándo puedo activar / desactivar restricciones de diseño?


He configurado varios conjuntos de restricciones en IB, y me gustaría alternar programáticamente entre ellos dependiendo de algún estado. Hay una constraintsA colección de tomas, todas marcadas como instaladas desde IB, y una constraintsB colección de salida que se desinstalan en IB.

Puedo alternar programáticamente entre los dos conjuntos así:

NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)

Pero ... no puedo entender cuando Para hacer eso. Parece que debería ser capaz de hacer eso una vez viewDidLoad, pero no puedo hacer que eso funcione. He intentado llamar view.updateConstraints() y view.layoutSubviews() después de establecer las restricciones, pero fue en vano.

Encontré que si establezco las restricciones en viewDidLayoutSubviews todo funciona como se espera Supongo que me gustaría saber dos cosas ...

  1. ¿Por qué estoy obteniendo este comportamiento?
  2. ¿Es posible activar / desactivar restricciones de viewDidLoad?

73
2017-12-15 22:46


origen


Respuestas:


Activo y desactivo NSLayoutConstraints en viewDidLoady no tengo ningún problema con eso Entonces funciona Debe haber una diferencia en la configuración entre su aplicación y la mía :-)

Simplemente describiré mi configuración, tal vez pueda darte una pista:

  1. Configuro @IBOutlets para todas las restricciones que necesito activar / desactivar.
  2. En el ViewController, Guardo las restricciones en propiedades de clase que no son débiles. La razón de esto es que descubrí que después de desactivar una restricción, no podía reactivarla, era nula. Por lo tanto, parece ser eliminado cuando está desactivado.
  3. No uso NSLayoutConstraint.deactivate/activate como tú, yo uso constraint.active = YES/NO en lugar.
  4. Después de establecer las restricciones, llamo view.layoutIfNeeded().

136
2018-02-25 10:57



tal vez podrías revisar su @propertiesreemplazar weak con strong.

A veces porque active = NO conjunto self.yourContraint = nilpara que no puedas usar self.yourContraint de nuevo.


28
2017-09-07 08:33



override func viewDidLayoutSubviews() {
// do it here, after constraints have been materialized
}

20
2018-01-05 03:16



Creo que el problema que está experimentando se debe a que no se han agregado restricciones a sus puntos de vista hasta DESPUÉS viewDidLoad() se llama. Tienes un número de opciones:

UN) Puede conectar sus restricciones de diseño a una IBOutlet y acceder a ellas en su código mediante estas referencias. Como las salidas están conectadas antes viewDidLoad() se inicia, las restricciones deben ser accesibles y puede continuar activándolas y desactivándolas allí.

SEGUNDO) Si desea usar UIView's constraints() función para acceder a las diversas limitaciones que debe esperar viewDidLayoutSubviews() para comenzar y hacerlo allí, ya que es el primer punto después de crear un controlador de vista desde un plumín que tendrá restricciones instaladas. No te olvides de llamar layoutIfNeeded() cuando termines. Esto tiene la desventaja de que el pase de disposición se ejecutará dos veces si se aplican cambios y debe asegurarse de que no haya posibilidad de que se active un ciclo infinito.

Una palabra de advertencia rápida: las limitaciones desactivadas NO son devueltas por  constraints()  ¡método! Esto significa que si DESACTIVA una restricción con la intención de volver a encenderla más tarde, deberá mantener una referencia.

DO) Puede olvidarse del enfoque del guión gráfico y agregar sus restricciones manualmente. Ya que estás haciendo esto en viewDidLoad() Supongo que la intención es hacerlo solo una vez durante toda la vida útil del objeto en lugar de cambiar el diseño sobre la marcha, por lo que este debería ser un método aceptable.


12
2018-03-01 09:51



El momento adecuado para desactivar las restricciones no utilizadas:

-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    self.myLittleConstraint.active = NO;
}

Manten eso en mente viewWillLayoutSubviews podría ser llamado varias veces, por lo que no hay cálculos pesados ​​aquí, ¿de acuerdo?

Nota: si quiere reactivar algunas de las restricciones más adelante, entonces siempre almacene strong referencia a ellos


7
2018-05-20 10:52



También puedes ajustar el priority propiedad para "habilitarlos" y "desactivarlos" (750 para habilitar y 250 para desactivar, por ejemplo). Por alguna razón, cambiar el active BOOL no tuvo ningún efecto en mi UI. No es necesario layoutIfNeeded y se puede establecer y cambiar en viewDidLoad o en cualquier momento después de eso.


7
2017-07-06 16:58



He encontrado siempre y cuando configure las restricciones por normal en la anulación de - (void)updateConstraints (objetivo c), con un strong referencia para la inicialidad utilizada restricciones activas y no activas. Y en cualquier otro lugar del ciclo de visualización, desactive y / o active lo que necesita, luego llame layoutIfNeeded, no deberías tener problemas.

Lo principal es no reutilizar constantemente la anulación de updateConstraints y para separar las activaciones de las restricciones, siempre y cuando llame updateConstraints después de su primera inicialización y diseño. Parece importar después de eso en qué parte del ciclo de visualización.


1
2018-03-27 10:25



Cuando se crea una vista, los siguientes métodos del ciclo de vida se llaman en orden:

  1. loadView
  2. viewDidLoad
  3. viewWillAppear
  4. viewWillLayoutSubviews
  5. viewDidLayoutSubviews
  6. viewDidAppear

Ahora a tus preguntas.

  1. ¿Por qué estoy obteniendo este comportamiento?

Respuesta: Porque cuando intentas establecer las restricciones en las vistas en viewDidLoad la vista no tiene sus límites, por lo tanto, no se pueden establecer restricciones. Solo después viewDidLayoutSubviews que los límites de la vista están finalizados.

  1. ¿Es posible activar / desactivar restricciones de viewDidLoad?

Respuesta: No. La razón explicada arriba.


-1
2018-03-01 19:49