Anidado UIStackViews Roto Restricciones

Tengo un complejo de vista de la jerarquía, construido en el Interface Builder, con anidada UIStackViews. Me sale «unsatisfiable las limitaciones de la» avisos cada vez que me ocultan algo en mi interior stackviews. He relacionarlo con esto:

(
    "<NSLayoutConstraint:0x1396632d0 'UISV-canvas-connection' UIStackView:0x1392c5020.top == UILabel:0x13960cd30'Also available on iBooks'.top>",
    "<NSLayoutConstraint:0x139663470 'UISV-canvas-connection' V:[UIButton:0x139554f80]-(0)-|   (Names: '|':UIStackView:0x1392c5020 )>",
    "<NSLayoutConstraint:0x139552350 'UISV-hiding' V:[UIStackView:0x1392c5020(0)]>",
    "<NSLayoutConstraint:0x139663890 'UISV-spacing' V:[UILabel:0x13960cd30'Also available on iBooks']-(8)-[UIButton:0x139554f80]>"
)

Específicamente, el UISV-spacing restricción: cuando se oculta un UIStackView su alta restricción obtiene un 0 constante, pero que parece entrar en conflicto con el interior de la stackview espaciado de la restricción: se requiere 8 puntos entre la Etiqueta y el Botón, que es inconciliable con la ocultación de la restricción y así las limitaciones de choque.

Hay una forma de evitar esto? He tratado de ocultar de forma recursiva todo el interior de la StackViews oculta de la pila de vista, pero que los resultados en extrañas animaciones en las que los contenidos que flota fuera de la pantalla, y causa graves FPS gotas de arranque, mientras que todavía no solucionar el problema.

InformationsquelleAutor Alex Popov | 2015-10-12

6 Kommentare

  1. 16

    Idealmente podríamos establecer la prioridad de la UISV-spacing restricción a un valor inferior, pero no parece haber ninguna manera de hacerlo. 🙂

    Estoy teniendo éxito configuración de la spacing propiedad de la anidados pila vistas a 0, antes de ocultarse, y restaurar el valor correcto después de hacer visible de nuevo.

    Yo creo que haciendo esto de forma recursiva en anidada pila opinión de trabajo. Usted podría almacenar el valor original de la spacing propiedad en un diccionario y restaurar más adelante.

    Mi proyecto solo tiene un nivel de anidamiento, así que estoy seguro de si esto podría resultar en problemas de FPS. Mientras usted no animar los cambios en el espaciado, no creo que crearía demasiada de un golpe.

    • gracias, voy a intentar que fuera hoy y aceptar la respuesta si funciona 🙂
  2. 25

    Este es un problema conocido con ocultar anidada de la pila de puntos de vista.

    Básicamente, hay 3 soluciones a este problema:

    1. Cambiar el espaciado a 0, pero entonces usted necesitará recordar el anterior valor de espaciado.
    2. Llamada innerStackView.removeFromSuperview(), pero entonces usted necesitará recordar dónde insertar la pila de vista.
    3. Envoltura de la pila de vista en un UIView con al menos uno de los 999 restricción. E. g. [email protected], lí[email protected], detrás de [email protected], [email protected]

    La 3ª opción es la mejor en mi opinión. Para obtener más información acerca de este problema, por qué ocurre, las diferentes soluciones, y cómo implementar la solución 3, ver mi respuesta a una pregunta similar.

    • Solución 3 funcionado para mí, me puso la pila de vista dentro de un UIView restringido a todos los bordes (como uno normal). Parece que la pila de vista no le gusta ser la raíz de la vista.
  3. 19

    Me golpeó un problema similar con UISV la clandestinidad. Para mí, la solución fue reducir las prioridades de mis propias limitaciones del Requerido (1000) a algo menos que eso. Cuando UISV-ocultar restringe la que se agregan, que tienen prioridad y las limitaciones que ya no choque.

    • el problema es que no tengo limitaciones de mi propia sobre los elementos 🙁 sin embargo, esto hizo que resolver otros problemas similares en el caso de que yo hice.
    • He tenido un problema similar y esta arreglado para mí.
    • Holy cow! Después de un día de reflexión, preguntando, y algunos graves lluvia de ideas, esta era. Tiene sentido que el UIStackView operará en las restricciones que no vemos, pero inherentemente conflicto con nuestras limitaciones. Gran respuesta, gracias @Jaanus!
    • El cambio de las prioridades también trabajó para mí. También, la eliminación de cualquier exceso (atenuado) las Restricciones que fueron accidentalmente copiado desde no utilizados Clases de Tamaño. CONSEJO IMPORTANTE: para mayor facilidad de depuración de estos problemas, establecer un IDENTIFICADOR de cadena en cada Restricción. A continuación, puede ver que la Restricción era ser malo en el mensaje de depuración.
  4. 18

    Así, has esto:

    Anidado UIStackViews Roto Restricciones

    Y el problema es que, cuando la primera vez que colapso el interior de la pila, que se auto de errores de diseño:

    2017-07-02 15:40:02.377297-0500 nestedStackViews[17331:1727436] [LayoutConstraints] Unable to simultaneously satisfy constraints.
        Probably at least one of the constraints in the following list is one you don't want. 
        Try this: 
            (1) look at each constraint and try to figure out which you don't expect; 
            (2) find the code that added the unwanted constraint or constraints and fix it. 
    (
        "<NSLayoutConstraint:0x62800008ce90 'UISV-canvas-connection' UIStackView:0x7fa57a70fce0.top == UILabel:0x7fa57a70ffb0'Top Label of Inner Stack'.top   (active)>",
        "<NSLayoutConstraint:0x62800008cf30 'UISV-canvas-connection' V:[UILabel:0x7fa57d30def0'Bottom Label of Inner Sta...']-(0)-|   (active, names: '|':UIStackView:0x7fa57a70fce0 )>",
        "<NSLayoutConstraint:0x62000008bc70 'UISV-hiding' UIStackView:0x7fa57a70fce0.height == 0   (active)>",
        "<NSLayoutConstraint:0x62800008cf80 'UISV-spacing' V:[UILabel:0x7fa57a70ffb0'Top Label of Inner Stack']-(8)-[UILabel:0x7fa57d30def0'Bottom Label of Inner Sta...']   (active)>"
    )
    
    Will attempt to recover by breaking constraint 
    <NSLayoutConstraint:0x62800008cf80 'UISV-spacing' V:[UILabel:0x7fa57a70ffb0'Top Label of Inner Stack']-(8)-[UILabel:0x7fa57d30def0'Bottom Label of Inner Sta...']   (active)>
    
    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

    El problema, como usted ha dicho, es que el exterior de la pila de vista se aplica una altura = 0 restricción para el interior de la pila de vista. Esto entra en conflicto con el punto 8 de relleno de la restricción aplicada por el interior de la pila de vista entre su propia subvistas. Tanto las restricciones no pueden ser satisfechos simultáneamente.

    El exterior de la pila de vista de los usos de esta altura = 0 restricción, creo, porque se ve mejor cuando animados que simplemente dejar que el interior se oculta, sin reducir primera.

    Hay una solución simple para esto: envuelva el interior de la pila de vista en un plano UIView, y ocultar que el contenedor. Voy a demostrar.

    Aquí está la escena esquema para la versión rota de arriba:

    Anidado UIStackViews Roto Restricciones

    Para solucionar el problema, seleccione el interior de la pila de vista. Desde la barra de menús, elija Editor > Incrustar En > Vista:

    Anidado UIStackViews Roto Restricciones

    Interface Builder crea un ancho de restricción en el contenedor de vista cuando hice esto, para eliminar ese ancho de restricción:

    Anidado UIStackViews Roto Restricciones

    Siguiente, crear restricciones entre los cuatro bordes de la envoltura y el interior de la pila de vista:

    Anidado UIStackViews Roto Restricciones

    En este punto, el diseño es realmente correcta en tiempo de ejecución, pero el Interfaz del Generador de sorteos de forma incorrecta. Se puede solucionar mediante la configuración de la vertical abrazos prioridades del interior de la pila de los niños mayores. Me puse a 800:

    Anidado UIStackViews Roto Restricciones

    Realidad no hemos solucionado el unsatisfiable restringir el problema en este punto. Para ello, encontrar el fondo de la restricción de que usted acaba de crear y establecer su prioridad, a menos que lo necesario. Vamos a cambiarlo a 800:

    Anidado UIStackViews Roto Restricciones

    Por último, presumiblemente tenía una salida en su vista controlador conectado a la interna de la pila de vista, debido a que estaban cambiando su hidden de la propiedad. El cambio que toma para conectar el contenedor de vista en lugar de en el interior de la pila de vista. Si la toma de corriente del tipo de UIStackView, entonces usted necesitará cambiar a UIView. El mío era ya de tipo UIView, así que sólo he vuelto a conectar en el guión gráfico:

    Anidado UIStackViews Roto Restricciones

    Ahora, al cambiar el contenedor de la vista hidden de la propiedad, la pila de vista aparecerá al colapso, sin unsatisfiable restricción de las advertencias. Se ve prácticamente idénticos, por lo que no voy a molestar a publicar otro GIF de la aplicación en ejecución.

    Usted puede encontrar en mi proyecto de prueba en este repositorio de github.

    • Tenga en cuenta también que usted puede cambiar fácilmente el efecto de animación utilizando el contenedor de vista. Intente encender «los Clips de los Límites» en la envoltura de la vista y la configuración de la parte inferior de la restricción prioridad a 600. Obtendrá un bonito slide-bajo efecto en lugar de un aplastándola efecto.
  5. 2

    Otro enfoque

    Tratar de evitar anidada UIStackViews. Me encanta y construir casi de todo con ellos. Pero como ya he reconocido que secretamente agregar restricciones trato de usarlos solo en el nivel más alto y no anidada donde sea posible. De esta forma, se puede especificar la 2ª más alta prioridad .defaultHigha la separación de la restricción de la que se resuelve mis advertencias.

    Esta prioridad es sólo lo suficiente para evitar la mayoría de problemas de diseño.

    De curso necesita especificar más limitaciones pero de esta manera usted tiene el control total de ellos y hacer su diseño de vista explícito.

  6. 0

    Aquí la aplicación de Senseful sugerencia #3 escrito como Swift 3 clase utilizando SnapKit restricciones. También intenté reemplazar las propiedades, pero nunca consiguió trabajo sin advertencias, así que me quedo con envoltura UIStackView:

    class NestableStackView: UIView {
        private var actualStackView = UIStackView()
    
        override init(frame: CGRect) {
            super.init(frame: frame);
            addSubview(actualStackView);
            actualStackView.snp.makeConstraints { (make) in
                //Lower edges priority to allow hiding when spacing > 0
                make.edges.equalToSuperview().priority(999);
            }
        }
    
        convenience init() {
            self.init(frame: CGRect.zero);
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        func addArrangedSubview(_ view: UIView) {
            actualStackView.addArrangedSubview(view);
        }
    
        func removeArrangedSubview(_ view: UIView) {
            actualStackView.removeArrangedSubview(view);
        }
    
        var axis: UILayoutConstraintAxis {
            get {
                return actualStackView.axis;
            }
            set {
                actualStackView.axis = newValue;
            }
        }
    
        open var distribution: UIStackViewDistribution {
            get {
                return actualStackView.distribution;
            }
            set {
                actualStackView.distribution = newValue;
            }
        }
    
        var alignment: UIStackViewAlignment {
            get {
                return actualStackView.alignment;
            }
            set {
                actualStackView.alignment = newValue;
            }
        }
    
        var spacing: CGFloat {
            get {
                return actualStackView.spacing;
            }
            set {
                actualStackView.spacing = newValue;
            }
        }
    }

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Recent Articles

Python «set» con duplicados/elementos repetidos

Hay una forma estándar de representar un "conjunto" que puede contener elementos duplicados. Como yo lo entiendo, un conjunto tiene exactamente un cero o...

Python: generador de expresión vs rendimiento

En Python, ¿hay alguna diferencia entre la creación de un generador de objetos a través de un generador de expresión versus el uso de...

Cómo exportar/importar la Masilla lista de sesiones?

Hay una manera de hacer esto? O tengo que tomar manualmente cada archivo de Registro? InformationsquelleAutor s.webbandit | 2012-10-23

no distingue mayúsculas de minúsculas coincidentes en xpath?

Por ejemplo, para el xml a continuación <CATALOG> <CD title="Empire Burlesque"/> <CD title="empire burlesque"/> <CD...