recuerdo - restricciones ios 12
¿Cuándo puedo activar/desactivar restricciones de diseño? (8)
Creo que el problema que está experimentando se debe a que las restricciones no se agregan a sus vistas hasta que se viewDidLoad()
DESPUÉS de viewDidLoad()
. Tienes un número de opciones:
A) 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 de que se viewDidLoad()
, las restricciones deben estar accesibles y puede continuar activándolas y desactivándolas allí.
B) Si desea usar la función constraints()
UIView para acceder a las diversas restricciones, debe esperar a que viewDidLayoutSubviews()
y lo haga allí, ya que es el primer punto después de crear un controlador de vista desde un plumín que tendrá cualquier restricción instalada. No olvides llamar a layoutIfNeeded()
cuando hayas terminado. 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 restricciones desactivadas NO son devueltas por el método constraints()
! Esto significa que si DESACTIVA una restricción con la intención de volver a encenderla más tarde, deberá mantener una referencia.
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 del objeto en lugar de cambiar el diseño sobre la marcha, por lo que este debería ser un método aceptable.
He configurado varios conjuntos de restricciones en IB, y me gustaría alternar programáticamente entre ellos dependiendo de algún estado. Hay una colección constraintsA
outlet, todas marcadas como instaladas desde IB, y una colección de outlet constraintsB
, todas las cuales se desinstalan en IB.
Puedo alternar programáticamente entre los dos conjuntos así:
NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)
Pero ... No puedo imaginar cuándo hacer eso. Parece que debería poder hacerlo una vez en viewDidLoad
, pero no puedo hacer que funcione. Intenté llamar a view.updateConstraints()
y view.layoutSubviews()
después de configurar las restricciones, pero fue en vano.
Encontré que si establecía las restricciones en viewDidLayoutSubviews
todo funciona como se esperaba. Supongo que me gustaría saber dos cosas ...
- ¿Por qué estoy obteniendo este comportamiento?
- ¿Es posible activar / desactivar restricciones de viewDidLoad?
Cuando se crea una vista, los siguientes métodos del ciclo de vida se llaman en orden:
- loadView
- viewDidLoad
- viewWillAppear
- viewWillLayoutSubviews
- viewDidLayoutSubviews
- viewDidAppear
Ahora a tus preguntas.
- ¿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 de viewDidLayoutSubviews
finalizan los viewDidLayoutSubviews
la vista.
- ¿Es posible activar / desactivar restricciones de viewDidLoad?
Respuesta: No. La razón explicada arriba.
El momento adecuado para desactivar las restricciones no utilizadas:
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.myLittleConstraint.active = NO;
}
Tenga en cuenta que viewWillLayoutSubviews
podría ser llamado varias veces, por lo que no hay cálculos pesados aquí, ¿de acuerdo?
Nota: si desea reactivar algunas de las restricciones más adelante, siempre almacene strong
referencia strong
para ellas.
He encontrado que siempre que establezca las restricciones por normal en la anulación de - (void)updateConstraints
(objetivo c), con una referencia strong
para la inicialidad se usan restricciones activas y no activas. Y en cualquier otro lugar del ciclo de vista desactivar y / o activar lo que necesita, y luego llamar a layoutIfNeeded
, no debería tener problemas.
Lo principal es no reutilizar constantemente la anulación de updateConstraints
y separar las activaciones de las restricciones, siempre que llame a updateConstraint
s después de su primera inicialización y diseño. Parece importar después de eso en qué parte del ciclo de visualización.
Tal vez podría verificar sus @properties
, reemplazar weak
con strong
.
A veces es porque active = NO
configuró self.yourContraint = nil
, por lo que no podría usar self.yourContraint
nuevamente.
También puede ajustar la propiedad de priority
para "habilitar" y "deshabilitar" (valor 750 para habilitar y 250 para deshabilitar, por ejemplo). Por alguna razón, cambiar el BOOL active
no tuvo ningún efecto en mi UI. No hay necesidad de layoutIfNeeded
y se puede establecer y cambiar en viewDidLoad o en cualquier momento después de eso.
NSLayoutConstraints
y desactivo NSLayoutConstraints
en viewDidLoad
, y no tengo ningún problema con él. 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:
- Configuré
@IBOutlets
para todas las restricciones que necesito activar / desactivar. - En
ViewController
,ViewController
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. - No uso
NSLayoutConstraint.deactivate/activate
como lo haces, utilizoconstraint.active = YES
/NO
lugar. - Después de establecer las restricciones, llamo
view.layoutIfNeeded()
.
override func viewDidLayoutSubviews() {
// do it here, after constraints have been materialized
}