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 puntos de venta que están marcados como instalados desde IB y una constraintsB
colecció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 viewDidLayoutSubviews
todo 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
NSLayoutConstraints
enviewDidLoad
, 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:
@IBOutlets
todas 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/activate
como tú, usoconstraint.active = YES
/ en suNO
lugar.view.layoutIfNeeded()
.fuente
.active = false
esperando que fueran ignoradas hasta que las establezca como activas.Tal vez pueda revisar su
@properties
, reemplazarweak
constrong
.A veces, porque está
active = NO
configuradoself.yourConstraint = nil
, por lo que no se puede usar deself.yourConstraint
nuevo.fuente
weak
y 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
priority
propiedad para "habilitarlos" y "deshabilitarlos" (valor 750 para habilitar y 250 para deshabilitar, por ejemplo). Por alguna razón, cambiar elactive
BOOL no tuvo ningún efecto en mi interfaz de usuario. No es necesariolayoutIfNeeded
y 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
@IBOutlet
referencias aNSLayoutConstraint
-s.El momento adecuado para desactivar las restricciones no utilizadas:
Tenga en cuenta que
viewWillLayoutSubviews
podrí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
strong
referencia 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,
viewDidLoad
la vista no tiene sus límites, por lo tanto, no se pueden establecer restricciones. Es solo después deviewDidLayoutSubviews
que 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 unastrong
referencia 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
updateConstraints
y separar las activaciones de las restricciones, siempre que llame aupdateConstraint
s después de su primera inicialización y diseño. Parece importar después de eso en el ciclo de visualización.fuente