Ejemplo reproducible mínimo (Xcode 11.2 beta, esto funciona en Xcode 11.1):
struct Parent: View {
var body: some View {
NavigationView {
Text("Hello World")
.navigationBarItems(
trailing: NavigationLink(destination: Child(), label: { Text("Next") })
)
}
}
}
struct Child: View {
@Environment(\.presentationMode) var presentation
var body: some View {
Text("Hello, World!")
.navigationBarItems(
leading: Button(
action: {
self.presentation.wrappedValue.dismiss()
},
label: { Text("Back") }
)
)
}
}
struct ContentView: View {
var body: some View {
Parent()
}
}
El problema parece radicar en colocar mi NavigationLink
interior de un navigationBarItems
modificador que está anidado dentro de una vista SwiftUI cuya vista raíz es a NavigationView
. El informe de bloqueo indica que estoy intentando abrir un controlador de vista que no existe cuando navego hacia adelante Child
y luego hacia atrás Parent
.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to pop to a view controller that doesn't exist.'
*** First throw call stack:
Si tuviera que colocar eso NavigationLink
en el cuerpo de la vista como el siguiente, funciona bien.
struct Parent: View {
var body: some View {
NavigationView {
NavigationLink(destination: Child(), label: { Text("Next") })
}
}
}
¿Es esto un error de SwiftUI o un comportamiento esperado?
EDITAR: he abierto un problema con Apple en su asistente de comentarios con la ID FB7423964
en caso de que a alguien de Apple le importe pesar :).
EDITAR: Mi boleto abierto en el asistente de comentarios indica que hay más de 10 problemas similares reportados. Han actualizado la resolución con Resolution: Potential fix identified - For a future OS update
. Los dedos cruzaron que la solución aterriza pronto.
EDITAR: ¡Esto se ha solucionado en iOS 13.3!
ContentView.swift
. Haré una edición en la publicación, pero el bloqueo solo ocurre cuando navegas hacia adelante y luego hacia atrás.Respuestas:
¡Este fue un punto de dolor para mí! Lo dejé hasta que se completó la mayor parte de mi aplicación y tuve el espacio mental para lidiar con el bloqueo.
Creo que todos podemos estar de acuerdo en que hay algunas cosas bastante impresionantes con SwifUI, pero que la depuración puede ser difícil.
En mi opinión, diría que esto es un ERROR. Aquí está mi justificación:
Si ajusta la llamada de rechazo de PresentationMode en un retraso asíncrono de aproximadamente medio segundo, debería encontrar que el programa ya no se bloqueará.
Esto me sugiere que el error es un comportamiento inesperado en el fondo de cómo SwiftUI interactúa con todos los demás códigos UIKit para administrar las diversas vistas. Dependiendo de su código real, puede encontrar que si hay alguna complejidad menor en la vista, el bloqueo en realidad no sucederá. Por ejemplo, si está descartando de una vista a una que tiene una lista, y esa lista está vacía, obtendrá un bloqueo sin el retraso asincrónico. Por otro lado, si tiene solo una entrada en esa vista de lista, forzando una iteración de bucle para generar la vista principal, verá que no se producirá el bloqueo.
No estoy tan seguro de cuán robusta es mi solución de terminar la llamada de rechazo en un retraso. Tengo que probarlo mucho más. Si tiene ideas sobre esto, ¡hágamelo saber! ¡Estaré muy feliz de aprender de ti!
fuente
.navigationBarItems()
puntos para que esto sea un error.Esto también me ha frustrado durante bastante tiempo. En los últimos meses, dependiendo de la versión de Xcode, la versión del simulador y el tipo y / o versión del dispositivo real, ha pasado de funcionar a fallar a funcionar nuevamente, aparentemente al azar. Sin embargo, recientemente ha estado fallando constantemente para mí, así que ayer me sumergí profundamente en él. Actualmente estoy usando Xcode versión 11.2.1 (11B500).
Parece que el problema gira en torno a la barra de navegación y la forma en que se le agregaron los botones. Entonces, en lugar de usar un NavigationLink () para el botón en sí, intenté usar un botón estándar () con una acción que establece un @State var que activa un NavigationLink oculto. Aquí hay un reemplazo para Robert's Parent View:
Para mí, esto funciona de manera muy consistente en todos los simuladores y todos los dispositivos reales.
Aquí están mis puntos de vista de ayuda:
Aquí hay un ejemplo del uso:
fuente
Este es un error importante y no puedo ver una forma adecuada de solucionarlo. Funcionó bien en iOS 13 / 13.1 pero se bloquea 13.2.
En realidad, puede replicarlo de una manera mucho más simple (este código es, literalmente, todo lo que necesita).
Espero que Apple lo resuelva, ya que seguramente romperá un montón de aplicaciones SwiftUI (incluida la mía).
fuente
Como solución alternativa, según la respuesta de Chuck H anterior, he encapsulado el NavigationLink como un elemento oculto:
Luego puede usarlo dentro de un NavigationView (que es crucial) y activarlo desde un Botón en una barra de navegación:
Envuelva esto en comentarios "// HACK" para que cuando Apple corrija esto pueda reemplazarlo.
fuente
Basado en la información que ustedes proporcionaron y especialmente en un comentario que hizo @Robert sobre dónde se ubica el NavigationView, he encontrado una manera de solucionar el problema, al menos en mi escenario específico.
En mi caso, tenía un TabView que estaba encerrado en un NavigationView como este:
Este código falla cuando todos informan en iOS 13.2 y funciona en iOS 13.1. Después de algunas investigaciones, descubrí una solución a esta situación.
Básicamente, estoy moviendo el NavigationView a cada pantalla por separado en cada pestaña de esta manera:
De alguna manera va en contra de la premisa de simplicidad de SwiftUI, pero funciona en iOS 13.2.
fuente
Xcode 11.2.1 Swift 5
¡ENTENDIDO! Me tomó un par de días resolver esto ...
En mi caso, cuando uso SwiftUI, tengo un bloqueo solo si la parte inferior de mi lista se extiende más allá de la pantalla y luego trato de "mover" cualquier elemento de la lista. Lo que terminé descubriendo es que si tengo demasiadas "cosas" debajo de la Lista (), entonces se bloquea en el movimiento. Por ejemplo, debajo de mi Lista () tenía un Texto (), Espaciador (), Botón (), Botón Espaciador () (). Si comenté UNO de esos objetos, de repente no pude recrear el bloqueo. No estoy seguro de cuáles son las limitaciones, pero si tiene este bloqueo, intente eliminar los objetos debajo de su lista para ver si ayuda.
fuente
Aunque no puedo ver ningún bloqueo, su código tiene algunos problemas:
al configurar el elemento principal, en realidad elimina el comportamiento predeterminado de las transiciones de navegación. (intente deslizar desde el lado delantero para ver si funciona).
Así que no es necesario tener un botón allí. Simplemente déjelo como está y tendrá un botón de retroceso gratuito.
Y no se olvide de acuerdo con HIG , el título del botón de retroceso debe mostrar a dónde va, ¡ no lo que es! Por lo tanto, intente configurar un título para la primera página para mostrarle el botón de retroceso que aparece.
fuente
FWIW: las soluciones anteriores que sugieren un NavigationLink Hack oculto sigue siendo la mejor solución en iOS 13.3b3. También he presentado un FB7386339 por el bien de la posteridad, y se cerró de manera similar a otros FB mencionados anteriormente: "Solución potencial identificada - Para una futura actualización del sistema operativo".
Dedos cruzados.
fuente
Está resuelto en iOS 13.3. Simplemente actualice su sistema operativo y xCode.
fuente
.buttonStyle(PlainButtonStyle())
modificador NavigationLink y vuelva a intentarlo. Avísame si hiciste una pregunta.