ios - metatags - meta tags generator
UIStackView: problemas de restricción de diseño al ocultar vistas de pila (12)
Mi aplicación tiene 2 pantallas:
TableViewVC (sin vistas de pila aquí)
DetailVC (todas las vistas de pila anidadas aquí; vea el enlace para ver la imagen: Imagen de vista de pila anidada) - Tenga en cuenta que hay etiquetas e imágenes dentro de estas vistas de pila.
Cuando presiona una celda en la vista de tabla, pasa la información de TableViewVC a DetailVC. El problema está en ocultar las UIStackViews específicas en DetailVC. Solo quiero que se oculten 2 vistas de pila de las diferentes en DetailVC tan pronto como se cargue la vista. Así que escribo este código en DetailVC para lograr esto:
override func viewDidLoad() {
super.viewDidLoad()
self.nameLabel.text = "John"
self.summaryStackView.hidden = true
self.combinedStackView.hidden = true
}
Todo se ve bien, pero Xcode da muchas advertencias solo en tiempo de ejecución . No hay ninguna advertencia en Storyboard cuando la aplicación no se está ejecutando. Por favor vea el enlace para la imagen de los errores: Imagen de los errores
Básicamente es una gran cantidad de errores de UISV-ocultación, UISV-separación, UISV-canvas-connection. Estos errores desaparecen si viewDidAppear
las mismas vistas de pila en viewDidAppear
pero luego hay un flash de las cosas que se suponía que estaban ocultas y luego se esconden. El usuario ve la vista brevemente y luego oculta lo que no es bueno.
Lo siento por no poder publicar imágenes en lugar de enlaces, aún no puedo hacerlo.
Alguna sugerencia en como arreglar esto? Esto es para una aplicación que realmente quiero lanzar a la tienda de aplicaciones. ¡Es mi primera vez, así que cualquier ayuda sería excelente!
Editar / Actualizar 1:
Encontré una pequeña solución con este código que puse dentro de la segunda pantalla llamada DetailVC:
// Function I use to delay hiding of views
func delay(delay: Double, closure: ()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
// Hide the 2 stack views after 0.0001 seconds of screen loading
override func awakeFromNib() {
delay(0.001) { () -> () in
self.summaryStackView.hidden = true
self.combinedStackView.hidden = true
}
}
// Update view screen elements after 0.1 seconds in viewWillAppear
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
delay(0.1) { () -> () in
self.nameLabel.text = "John"
}
}
Esto elimina las advertencias sobre las restricciones de diseño completamente de Xcode.
Todavía no es perfecto porque a veces veo un vislumbre de las vistas que se supone que deben estar ocultas: parpadean muy rápido en la pantalla y luego desaparecen. Sin embargo, esto sucede muy rápido.
¿Alguna sugerencia de por qué esto se deshace de las advertencias? Además, ¿alguna sugerencia sobre cómo mejorar esto para que funcione perfectamente? ¡Gracias!
¿Has probado esto, llamando al super después de tus cambios?
override func viewWillAppear() {
self.nameLabel.text = "John"
self.summaryStackView.hidden = true
self.combinedStackView.hidden = true
super.viewWillAppear()
}
Cuando se oculta UIViewStack, las restricciones generadas automáticamente por UIStackView arrojarán muchas advertencias de UISV-ocultación, UISV-separación, UISV-canvas-connection, si la propiedad de separación de UIStackView tiene un valor distinto de cero.
Esto no tiene mucho sentido, es casi seguro que es un error de marco. La solución que utilizo es establecer el espaciado en cero al ocultar el componente.
if hideStackView {
myStackView.hidden = true
myStackView.spacing = CGFloat(0)
} else {
myStackView.hidden = false
myStackView.spacing = CGFloat(8)
}
Este error no se trata de ocultar, sino de restricciones ambiguas. No debe tener restricciones ambiguas en su opinión. Si los agrega mediante programación, debe comprender exactamente qué restricciones agrega y cómo funcionan juntas. Si no los agrega programáticamente, pero usa storyboard o xib, que es un buen lugar para comenzar, asegúrese de que no haya errores de restricción o advertencias.
UPD: Tienes una estructura de vistas bastante compleja allí. Sin ver las limitaciones es difícil decir qué es exactamente lo que está mal. Sin embargo, sugeriría construir una jerarquía de vistas gradualmente agregando vistas una por una y asegurándome de que no haya advertencias en tiempo de diseño / tiempo de ejecución. La vista de desplazamiento puede agregar otro nivel de complejidad si no lo manejas correctamente. Descubra cómo utilizar restricciones con una vista de desplazamiento. Todos los demás hacks de tiempo no es una solución de todos modos.
Este es un problema conocido con la ocultación de vistas de pila anidadas.
Hay esencialmente 3 soluciones a este problema:
- Cambie el espaciado a 0, pero luego necesitará recordar el valor de espaciado anterior.
- Llame a
innerStackView.removeFromSuperview()
, pero luego necesitará recordar dónde insertar la vista de pila. - Envuelva la vista de pila en una vista UIV con al menos una restricción de 999. Ej. Arriba, Líder, Arrastre @ 1000, Abajo @ 999.
La tercera opción es la mejor en mi opinión. Para obtener más información sobre este problema, por qué sucede, las diferentes soluciones y cómo implementar la solución 3, vea mi respuesta a una pregunta similar .
He encontrado que UIStackViews anidado muestra este comportamiento si configura la propiedad oculta en ✨Interface Builder✨. Mi solución fue configurar todo para que no esté oculto en ✨Interface Builder✨, y ocultar las cosas en viewWillAppear selectivamente.
Hice esto almacenando todas las vistas ocultas de UIStackView anidadas en una matriz y eliminándolas de las vistas de supervisión y las subvistas organizadas. Cuando quise que volvieran a aparecer, hice un bucle a través de la matriz y los volví a agregar. Este fue el primer paso.
El segundo paso es después de eliminar las vistas del UIStackView anidado de la vista de supervisión que el UIStackView principal aún no ajusta su altura. Puede solucionar este problema eliminando el UIStackView anidado y agregándolo de nuevo directamente después:
UIStackView *myStackView;
NSUInteger positionOfMyStackView = [parentStackView indexOfObject:myStackView];
[parentStackView removeArrangedSubview:myStackView];
[myStackView removeFromSuperview];
[parentStackView insertArrangedSubview:myStackView atIndex:positionOfMyStackView];
Lo arreglé poniendo los comandos de ocultar en traitCollectionDidChange.
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
self.item.hidden = true
}
Moví todo el código UIStackView.hidden de viewDidLoad a viewDidAppear y el problema de las restricciones rotas desapareció. En mi caso, todas las restricciones en conflicto se generaron automáticamente, por lo que no hay manera de ajustar las prioridades.
También utilicé este código para hacerlo más bonito:
UIView.animateWithDuration(0.5) {
self.deliveryGroup.hidden = self.shipVia != "1"
}
EDITAR:
También se necesita el siguiente código para evitar que vuelva a suceder cuando se gira el dispositivo:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
self.deliveryGroup.hidden = false
coordinator.animateAlongsideTransition(nil) {
context in
self.deliveryGroup.hidden = self.shipVia != "1"
}
}
Ponga sus comandos de ocultar en viewWillLayoutSubviews() {}
Por lo tanto, esto solo puede ayudar al 0.000001% de los usuarios, pero quizás se trate de un problema de límites a límites.
Me encontré con esto recientemente cuando trabajaba con UICollectionViewCell
. Olvidé revisar los clips hasta los límites de la vista que estaba considerando como mi vista de contenido. Al crear un UITableViewCell
en IB, se configura una vista de contenido con clips a límites como el valor predeterminado.
El punto es que, dependiendo de su situación, puede lograr el efecto deseado utilizando marcos y recorte.
Puede usar la propiedad removeArrangedSubview y removeFromSuperview de UIStackView.
En Objective-C:
[self.topStackView removeArrangedSubview:self.summaryStackView];
[self.summaryStackView removeFromSuperview];
[self.topStackView removeArrangedSubview:self.combinedStackView];
[self.combinedStackView removeFromSuperview];
De la documentación de Apple UIStackView :( https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIStackView_Class_Reference/#//apple_ref/occ/instm/UIStackView/removeArrangedSubview :)
La vista de pila actualiza automáticamente su diseño cada vez que las vistas se agregan, eliminan o insertan en la matriz de organizadas subvistas.
- removeArrangedSubview: este método elimina la vista provista de la matriz de las vistas organizadas de la pila. La posición y el tamaño de la vista ya no serán administrados por la vista de pila. Sin embargo, este método no elimina la vista proporcionada de la matriz de subvistas de la pila; por lo tanto, la vista aún se muestra como parte de la jerarquía de vistas.
Para evitar que la vista aparezca en la pantalla después de llamar al método removeArrangedSubview: de la pila, elimine explícitamente la vista de la matriz de subvistas llamando al método removeFromSuperview de la vista, o establezca la propiedad oculta de la vista en YES.
Tuve el mismo problema y lo solucioné dando a las restricciones de altura de mis vistas inicialmente ocultas una prioridad de 999.
El problema es que su vista de pila aplica una restricción de altura de 0 en su vista oculta que entra en conflicto con su otra restricción de altura. Este fue el mensaje de error:
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. (Note: If you''re seeing NSAutoresizingMaskLayoutConstraints that you don''t understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fa3a5004310 V:[App.DummyView:0x7fa3a5003fd0(40)]>",
"<NSLayoutConstraint:0x7fa3a3e44190 ''UISV-hiding'' V:[App.DummyView:0x7fa3a5003fd0(0)]>"
)
Darle a tu restricción de altura una prioridad más baja resuelve este problema.