He configurado varios conjuntos de restricciones en IB, y me gustaría alternar programáticamente entre ellos dependiendo de algún estado. Hay una constraintsAcolección de puntos de venta que están marcados como instalados desde IB y una constraintsBcolección de puntos de venta que se desinstalan en IB.
Puedo alternar programáticamente entre los dos conjuntos así:
NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)
Pero ... no sé cuándo hacer eso. Parece que debería poder hacer eso una vez viewDidLoad, pero no puedo hacer que funcione. Intenté llamar view.updateConstraints()y view.layoutSubviews()después de establecer las restricciones, pero fue en vano.
Descubrí que si establezco las restricciones en viewDidLayoutSubviewstodo funciona como se esperaba. Supongo que me gustaría saber dos cosas ...
- ¿Por qué tengo este comportamiento?
- ¿Es posible activar / desactivar restricciones desde viewDidLoad?
fuente

Respuestas:
Activo y desactivo
NSLayoutConstraintsenviewDidLoad, y no tengo ningún problema con él. Entonces funciona. Debe haber una diferencia en la configuración entre tu aplicación y la mía :-)Solo describiré mi configuración, tal vez pueda darte una pista:
@IBOutletstodas las restricciones que necesito activar / desactivar.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. Entonces, parece que se elimina cuando se desactiva.NSLayoutConstraint.deactivate/activatecomo tú, usoconstraint.active = YES/ en suNOlugar.view.layoutIfNeeded().fuente
.active = falseesperando que fueran ignoradas hasta que las establezca como activas.Tal vez pueda revisar su
@properties, reemplazarweakconstrong.A veces, porque está
active = NOconfiguradoself.yourConstraint = nil, por lo que no se puede usar deself.yourConstraintnuevo.fuente
weaky eso lo hará.fuente
Creo que el problema que está experimentando se debe a que las restricciones no se agregan a sus vistas hasta que
viewDidLoad()se llama AFTER . Tienes un número de opciones:A) Puede conectar sus restricciones de diseño a un IBOutlet y acceder a ellas en su código mediante estas referencias. Dado que los puntos de venta están conectados antes del
viewDidLoad()inicio, las restricciones deben ser accesibles y puede continuar activándolas y desactivándolas allí.B) Si desea utilizar la
constraints()función de UIView para acceder a las diversas restricciones, debe esperar aviewDidLayoutSubviews()que se inicie y hacerlo allí, ya que ese es el primer punto después de crear un controlador de vista a partir de una plumilla que tendrá las restricciones instaladas. No olvide llamarlayoutIfNeeded()cuando haya terminado. Esto tiene la desventaja de que el pase de diseño se realizará dos veces si hay algún cambio que aplicar y debe asegurarse de que no haya posibilidad de que se active un bucle infinito.Una advertencia rápida: ¡el método NO devuelve las restricciones deshabilitadas
constraints()! Esto significa que si deshabilita una restricción con la intención de volver a activarla más adelante, deberá mantener una referencia a ella.C) Puede olvidarse del enfoque del guión gráfico y agregar sus restricciones manualmente. Dado que está 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.fuente
También puede ajustar la
prioritypropiedad para "habilitarlos" y "deshabilitarlos" (valor 750 para habilitar y 250 para deshabilitar, por ejemplo). Por alguna razón, cambiar elactiveBOOL no tuvo ningún efecto en mi interfaz de usuario. No es necesariolayoutIfNeededy se puede configurar y cambiar en viewDidLoad o en cualquier momento posterior.fuente
viewWillTransition(to:, with:)oviewWillLayoutSubviews()y puede mantener todas sus restricciones alternativas como "instaladas" en un guión gráfico. Es posible que la prioridad de la restricción no cambie de no obligatoria a obligatoria, por lo que debe utilizar los valores siguientes1000. Por otro lado, activar (agregar) y desactivar (eliminar) restricciones solo funciona enviewDidLayoutSubviews()y requiere mantenerstrong@IBOutletreferencias aNSLayoutConstraint-s.El momento adecuado para desactivar las restricciones no utilizadas:
Tenga en cuenta que
viewWillLayoutSubviewspodría llamarse varias veces, por lo que no hay cálculos pesados aquí, ¿de acuerdo?Nota: si desea reactivar algunas de las restricciones más adelante, almacene siempre la
strongreferencia a ellas.fuente
viewDidLayoutSubviews(). Ajustar las restricciones enviewWillLayoutSubviews()no funciona en mi caso.Cuando se crea una vista, se llaman en orden los siguientes métodos de ciclo de vida:
Ahora a tus preguntas.
Respuesta: Porque cuando intenta establecer las restricciones en las vistas,
viewDidLoadla vista no tiene sus límites, por lo tanto, no se pueden establecer restricciones. Es solo después deviewDidLayoutSubviewsque se finalizan los límites de la vista.Respuesta: No. Razón explicada anteriormente.
fuente
He encontrado siempre que configure las restricciones por normal en la anulación de
- (void)updateConstraints(objetivo c), con unastrongreferencia para la inicialidad utilizada restricciones activas y no activas. Y en otra parte del ciclo de vista, desactive y / o active lo que necesita, luego llamelayoutIfNeeded, no debería tener problemas.Lo principal es no reutilizar constantemente la anulación
updateConstraintsy separar las activaciones de las restricciones, siempre que llame aupdateConstraints después de su primera inicialización y diseño. Parece importar después de eso en el ciclo de visualización.fuente