Cuando mis "filas" de UIStackView se aplastan, lanzan AutoLayout
advertencias. Sin embargo, se muestran bien y nada más está mal además de este tipo de registros:
Incapaz de satisfacer simultáneamente las limitaciones. Probablemente, al menos una de las restricciones de la siguiente lista sea una que no desee. Intente esto: (1) observe cada restricción e intente averiguar cuál no espera; (2) encuentre el código que agregó la restricción o restricciones no deseadas y corríjalo. (Nota: si ve
NSAutoresizingMaskLayoutConstraints
que no comprende, consulte la documentación de laUIView
propiedadtranslatesAutoresizingMaskIntoConstraints
) (
Entonces, no estoy seguro de cómo solucionar esto todavía, pero no parece romper nada además de ser molesto.
alguien sabe como resolverlo? Curiosamente, las restricciones de diseño se etiquetan con bastante frecuencia con 'ocultación de UISV' , lo que indica que tal vez debería ignorar los mínimos de altura para las subvistas o algo en este caso.
fuente
Respuestas:
Obtiene este problema porque cuando configura una subvista desde adentro
UIStackView
a oculta, primero limitará su altura a cero para animarla.Recibí el siguiente error:
Lo que estaba tratando de hacer era colocar un
UIView
dentro de miUIStackView
que contenía unUISegmentedControl
recuadro de 8 puntos en cada borde.Cuando lo configuro como oculto, intentaría restringir la vista del contenedor a una altura cero, pero debido a que tengo un conjunto de restricciones de arriba a abajo, hubo un conflicto.
Para resolver el problema, cambié mi prioridad de restricciones superior e inferior de 8 puntos de 1000 a 999 para que la
UISV-hiding
restricción pueda tener prioridad si es necesario.fuente
Tenía un problema similar que no era fácil de resolver. En mi caso, tenía una vista de pila incrustada en una vista de pila. El UIStackView interno tenía dos etiquetas y un espaciado distinto de cero especificado.
Cuando llame a addArrangedSubview (), automáticamente creará restricciones similares a las siguientes:
Ahora, cuando intenta ocultar el innerStackView, obtiene una advertencia de restricciones ambiguas.
Para entender por qué, veamos primero por qué esto no sucede cuando
innerStackView.spacing
es igual a0
. Cuando llamainnerStackView.hidden = true
, @liamnichols estaba en lo correcto ...outerStackView
interceptará mágicamente esta llamada y creará una restricción de ocultación de UISV de0
altura con prioridad 1000 (obligatorio). Presumiblemente, esto es para permitir que los elementos en la vista de pila se animen fuera de la vista en caso de que su código oculto sea llamado dentro de un bloque. Desafortunadamente, no parece haber una forma de evitar que se agregue esta restricción. Sin embargo, no recibirá una advertencia "No se puede satisfacer simultáneamente las restricciones" (USSC), ya que sucede lo siguiente:UIView.animationWithDuration()
Es evidente que se pueden satisfacer esas 4 limitaciones. La vista de pila simplemente suaviza todo en un píxel de altura 0.
Ahora, volviendo al ejemplo con errores, si configuramos el
spacing
to2
, ahora tenemos estas restricciones:La vista de pila no puede tener una altura de 0 píxeles y su contenido una altura de 2 píxeles. Las limitaciones no se pueden satisfacer.
Nota: Puede ver este comportamiento con un ejemplo más simple. Simplemente agregue una UIView a una vista de pila como una subvista organizada. Luego, establezca una restricción de altura en esa UIView con una prioridad de 1000. Ahora intenta llamar a hide en eso.
Nota: Por alguna razón, esto solo sucedió cuando mi vista de pila era una subvista de UICollectionViewCell o UITableViewCell. Sin embargo, aún puede reproducir este comportamiento fuera de una celda llamando
innerStackView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
al siguiente ciclo de ejecución después de ocultar la vista de la pila interna.Nota: Incluso si intenta ejecutar el código en un UIView.performWithoutAnimations, la vista de la pila aún agregará una restricción de altura 0 que provocará la advertencia de USSC.
Hay al menos 3 soluciones para este problema:
spacing
a 0. Esto es molesto porque necesita revertir el proceso (y recordar el espaciado original) cada vez que muestra el contenido nuevamente.removeFromSuperview
. Esto es aún más molesto, ya que cuando invierte el proceso, debe recordar dónde insertar el elemento eliminado. Puede optimizar simplemente llamando a removeArrangedSubview y luego ocultándose, pero hay mucha contabilidad que aún debe hacerse.spacing
) en una UIView. Especifique al menos una restricción como prioridad no requerida (999 o menos). Esta es la mejor solución, ya que no tiene que llevar la contabilidad. En mi ejemplo, creé restricciones superior, inicial y final en 1000 entre la vista de pila y la vista de envoltura, luego creé una restricción de 999 desde la parte inferior de la vista de pila a la vista de envoltura. De esta manera, cuando la vista de la pila externa crea una restricción de altura cero, la restricción 999 se rompe y no ve la advertencia de USSC. (Nota: Esto es similar a la solución para ¿Debería establecerse el contentView.translatesAutoResizingMaskToConstraints de una subclase UICollectionViewCell enfalse
)?En resumen, las razones por las que obtiene este comportamiento son:
Si Apple (1) le hubiera permitido especificar la prioridad de las restricciones (especialmente de los espaciadores), o (2) le hubiera permitido optar por no participar en la restricción automática de ocultación de UISV , este problema se resolvería fácilmente.
fuente
UIStackView
niños de unaUIStackView
necesidad deben estar envueltos en unUIView
o solo el que estás buscando ocultar / mostrar?UIStackView
tienden a ser crípticos y difíciles de entender.La mayoría de las veces, este error se puede resolver reduciendo la prioridad de las restricciones para eliminar conflictos.
fuente
Cuando configura una vista como oculta,
UIStackview
intentará animarla. Si desea ese efecto, deberá establecer la prioridad correcta para las restricciones para que no entren en conflicto (como muchos han sugerido anteriormente).Sin embargo, si no le importa la animación (tal vez la esté ocultando en ViewDidLoad), entonces puede simplificar, lo
removeFromSuperview
que tendrá el mismo efecto pero sin ningún problema con las restricciones, ya que se eliminarán junto con la vista.fuente
Según la respuesta de @ Senseful, aquí hay una extensión UIStackView para envolver una vista de pila en una vista y aplicar las restricciones que él o ella recomienda:
En lugar de agregar su
stackView
, usestackView.wrapped()
.fuente
Primero, como han sugerido otros, asegúrese de que las restricciones que puede controlar, es decir, no las restricciones inherentes a UIStackView, estén configuradas con prioridad 999 para que puedan anularse cuando la vista esté oculta.
Si aún experimenta el problema, es probable que el problema se deba al espacio en los StackViews ocultos. Mi solución fue agregar un UIView como espaciador y establecer el espaciado UIStackView en cero. Luego, establezca las restricciones de View.height o View.width (dependiendo de una pila vertical u horizontal) al espaciado de StackView.
A continuación, ajuste las prioridades de resistencia a la compresión de contenido y de acogida de contenido de sus vistas recién agregadas. Es posible que también tenga que cambiar la distribución del StackView principal.
Todo lo anterior se puede hacer en Interface Builder. Además, es posible que deba ocultar / mostrar algunas de las vistas recién agregadas mediante programación para que no tenga espacios no deseados.
fuente
Recientemente luché con errores de diseño automático al ocultar un archivo
UIStackView
. En lugar de hacer un montón de libros y envoltoriosUIViews
, opté por crear una salida para míparentStackView
y para los niños que quiero ocultar / mostrar.En el guión gráfico, así es como se ve mi parentStack:
Tiene 4 niños y cada uno de los niños tiene un montón de vistas de pila dentro de ellos. Cuando oculta una vista de pila, si tiene elementos de IU que también son vistas de pila, verá una secuencia de errores de diseño automático. En lugar de esconderme, opté por eliminarlos.
En mi ejemplo,
parentStackViews
contiene una matriz de los 4 elementos: Vista de pila superior, StackViewNumber1, Vista de pila número 2 y Botón de parada. Sus índices enarrangedSubviews
son 0, 1, 2 y 3, respectivamente. Cuando quiero ocultar uno, simplemente loparentStackView's
arrangedSubviews
elimino de la matriz. Dado que no es débil, permanece en la memoria y puede volver a colocarlo en el índice deseado más tarde. No lo estoy reinicializando, por lo que se cuelga hasta que se necesita, pero no hincha la memoria.Entonces, básicamente, puedes ...
1) Arrastre IBOutlets para su pila principal y los elementos secundarios que desea ocultar / mostrar al guión gráfico.
2) Cuando desee ocultarlos, elimine la pila que desea ocultar de la
parentStackView's
arrangedSubviews
matriz.3) Llame
self.view.layoutIfNeeded()
conUIView.animateWithDuration
.Tenga en cuenta que los dos últimos stackViews no lo son
weak
. Debes tenerlos cerca para cuando los muestres.Digamos que quiero ocultar stackViewNumber2:
Entonces anímalo:
Si desea "mostrar"
stackViewNumber2
más tarde, puede insertarlo en elparentStackView
arrangedSubViews
índice deseado y animar la actualización.Descubrí que eso es mucho más fácil que llevar la contabilidad de las limitaciones, jugar con las prioridades, etc.
Si tiene algo que desea ocultar de forma predeterminada, puede colocarlo en el guión gráfico y eliminarlo
viewDidLoad
y actualizarlo sin que se use la animaciónview.layoutIfNeeded()
.fuente
Experimenté los mismos errores con las vistas de pila integradas, aunque todo funcionó bien en tiempo de ejecución.
Resolví los errores de restricción ocultando primero todas las vistas de la subpila (configuración
isHidden = true
) antes de ocultar la vista de la pila principal.Hacer esto no tuvo toda la complejidad de eliminar vistas subdispuestas, manteniendo un índice para cuando sea necesario volver a agregarlas.
Espero que esto ayude.
fuente
Senseful ha proporcionado una excelente respuesta a la raíz del problema anterior, así que iré directamente a la solución.
Todo lo que necesita hacer es establecer la prioridad de todas las restricciones de stackView por debajo de 1000 (999 hará el trabajo). Por ejemplo, si stackView está restringido a la izquierda, derecha, arriba y abajo a su supervista, entonces las 4 restricciones deben tener una prioridad menor que 1000.
fuente
Es posible que haya creado una restricción mientras trabajaba con una clase de cierto tamaño (por ejemplo, wCompact hRegular) y luego creó un duplicado cuando cambió a otra clase de tamaño (por ejemplo: wAny hAny). verifique las restricciones de los objetos de la interfaz de usuario en diferentes clases de tamaño y vea si hay anomalías con las restricciones. Debería ver las líneas rojas que indican restricciones en colisión. No puedo poner una imagen hasta que obtenga 10 puntos de reputación, lo siento: /
fuente
Quería ocultar todo el UIStackView a la vez, pero estaba obteniendo los mismos errores que el OP, esto lo solucionó:
fuente
priority = 1000
) a no requerida (priority <= 999
).Tenía una fila de botones con restricción de altura. Esto sucede cuando se oculta un botón. Establecer la prioridad de la restricción de altura de los botones en 999 ha resuelto el problema.
fuente
Este error no tiene nada que ver con UIStackView. Ocurre cuando tiene restricciones de conflicto con las mismas prioridades. Por ejemplo, si tiene una restricción indica que el ancho de su vista es 100, y tiene otra restricción al mismo tiempo indica que el ancho de la vista es el 25% de su contenedor. Obviamente, hay dos limitaciones en conflicto. La solución es eliminar uno de ellos.
fuente
NOP con [mySubView removeFromSuperview]. Espero que pueda ayudar a alguien :)
fuente