Tenía el siguiente código en Xcode 12.4 que funcionó perfectamente
ScrollView(.horizontal, showsIndicators: false) { LazyHGrid(rows: rows, spacing: 0) { HStack { if (type == "Quiz") { NavigationLink(destination: Quiz(id: quiz.id)) { VStack(alignment: .leading) { Text("Quiz") .font(.headline) .foregroundColor(.white) .padding(.top, 8) .padding(.leading) } .background(Color.green) .cornerRadius(12) .shadow(color: .green, radius: 3, x: 0.0, y: 0.0) } } else { NavigationLink(destination: Survey(id: survey.id)) { VStack(alignment: .leading) { Text("Survey") .font(.headline) .foregroundColor(.white) .padding(.top, 8) .padding(.leading) } .background(Color.green) .cornerRadius(12) .shadow(color: .green, radius: 3, x: 0.0, y: 0.0) } } // End If if (type == "Quiz") { NavigationLink(destination: QuizResults(id: quiz.id)) { VStack(alignment: .leading) { Text("Quiz Results") .font(.headline) .foregroundColor(.white) .padding(.top, 8) .padding(.leading) } .background(Color.blue) .cornerRadius(12) .shadow(color: .blue, radius: 3, x: 0.0, y: 0.0) } } else { NavigationLink(destination: SurveyResults(id: survey.id)) { VStack(alignment: .leading) { Text("Survey Results") .font(.headline) .foregroundColor(.white) .padding(.top, 8) .padding(.leading) } .background(Color.blue) .cornerRadius(12) .shadow(color: .blue, radius: 3, x: 0.0, y: 0.0) } } } .padding([.leading, .trailing], 25) } .frame(height: 100)Acabo de actualizar Xcode a 12.5 y lo anterior ya no funciona.
¿Funcionaba bien en 12.4?
Ahora, cuando hago clic en el elemento 'Cuestionario', comienza la transición a la Vista de cuestionario, que lo muestra, pero inmediatamente cierra la vista y vuelvo a la Vista de detalles.
¿Alguien puede ver lo que estoy haciendo mal y por qué ahora, según la actualización a 12.5, esto dejó de funcionar?
ACTUALIZAR
Refiné el código a la mínima forma reproducible posible. Lo que parece estar sucediendo es que tengo dos o más conjuntos de NavigationLink s.
el primero es el conjunto para navegar al usuario a la Prueba o a la Encuesta cuya declaración if dirige al usuario a la vista correcta para completar.
El problema en 12.5 es que el segundo conjunto en el que el usuario puede hacer clic para ver los resultados generales del cuestionario o la encuesta no funciona cuando se encuentra directamente después de la primera navegación.
Como dije antes, funcionó perfectamente en 12.4 pero parece que 12.5 no está de acuerdo. ¿Alguien puede ofrecer una mejor manera para que el usuario haga clic en un elemento para completar un cuestionario o encuesta o ver los resultados de un cuestionario o encuesta?
Tengo exactamente el mismo problema, todo funciona bien con Xcode 12.4.
https://developer.apple.com/forums/thread/677333
Trato de seguir este hilo, podría funcionar, pero en algunos casos, todavía tengo este error.
NavigationLink(destination: EmptyView()) { EmptyView() }
Aparentemente, puedes poner estas 3 líneas de código cerca de tu NavigationLink... ¡Si alguien tiene una mejor respuesta, realmente lo apreciaré!
¡Qué bicho tan horrible! Según mis pruebas y algunas búsquedas en Google, sucede cuando hay exactamente 2 enlaces de navegación en una vista. El código en la pregunta tiene 4, pero debido a las declaraciones if else, efectivamente solo hay 2 a la vez.
A menudo no sé cuántos enlaces de navegación tendré, ya que depende de los datos que haya agregado el usuario/cuántos resultados de búsqueda haya, etc. Para estar seguro, he creado un modificador tripleEmptyNavigationLink que he pegado al final de todas mis opiniones. Está resolviendo el comportamiento emergente, pero sigo recibiendo las advertencias "No se puede presentar". Me encantaría saber si alguien tiene algo mejor que esto!
import SwiftUI struct TripleEmptyNavigationLink: View { var body: some View { VStack { NavigationLink(destination: EmptyView()) {EmptyView()} NavigationLink(destination: EmptyView()) {EmptyView()} NavigationLink(destination: EmptyView()) {EmptyView()} } } } struct TripleEmptyNavigationLinkBackground: ViewModifier { func body(content: Content) -> some View { content .background(TripleEmptyNavigationLink()) } } extension View { func tripleEmptyNavigationLink()-> some View { self.modifier(TripleEmptyNavigationLinkBackground()) } }uso:
MyView() .tripleEmptyNavigationLink()Tengo exactamente el mismo problema.
mi código:
class NavigationManager: ObservableObject { static let shared: NavigationManager = { return NavigationManager() }() @Published var showingMain: Bool @Published var showingSub: Bool @Published var content: AnyView init() { showingMain = false showingSub = false content = AnyView(EmptyView()) } func forward<T:View>(content: @escaping () -> T ) { showView() self.content = AnyView(content()) } private func showView() { if !showingMain,!showingSub { showingMain = true } else if showingMain,!showingSub { showingSub = true } else if !showingMain,showingSub { showingMain = true } } } struct NavigationLinkGroup: View { @EnvironmentObject var navigationManager: NavigationManager var body: some View { Group { NavigationLink(destination: navigationManager.content, isActive: $navigationManager.showingMain) {EmptyView()} NavigationLink(destination: navigationManager.content, isActive: $navigationManager.showingSub) {EmptyView()} } } } struct ContentView: View { var body: some View { NavigationView { NavigationLinkGroup() } } }https://github.com/Ftrybe/CustomBackButtonOfSwiftUIApp/tree/master/CustomBackButtonOfSwiftUI
Como cualquier otra persona en iOS 14.5.1, mi aplicación se ve afectada por este terrible error. Tengo más de 3 enlaces de navegación en la página y no tuve la suerte de modificar los números de los enlaces de navegación (agregando un enlace de navegación ficticio) para obtener el comportamiento correcto.
Una solución que está bien para mí es agregar un NavigationLink condicionalmente a la vista.
En lugar de:
var body: some View { NavigationLink(destination: AnotherView(), isActive: $someCondition) { EmptyView() } }Tengo esto:
var body: some View { if someCondition { NavigationLink(destination: AnotherView(), isActive: $someCondition) { EmptyView() } } }El comportamiento no es exactamente el mismo, ya que pierde algo de animación de navegación, pero al menos tiene una aplicación que funciona nuevamente con una solución relativamente fácil de entender.
También puede cortocircuitarlo solo a 14.5 y el comportamiento normal en otros lugares:
/// Assumes this gets fixed by Apple until 14.6 is out var onIOS14_5: Bool { let systemVersion = UIDevice.current.systemVersion return systemVersion.starts(with: "14.5") } var body: some View { if !onIOS14_5 || someCondition { NavigationLink(destination: AnotherView(), isActive: $someCondition) { EmptyView() } } }Quizás esto ayude a alguien y esperemos que Apple arregle este error vergonzoso. Ahora quiero mi medio día de vuelta.
Agregar un enlace de navegación con una vista vacía no funcionó para mí. Resolví mi problema eliminando todos los NavigationLink s de ForEach y usando uno solo para controlar la navegación a la vista detallada, un gesto de toque y 2 variables de estado para realizar un seguimiento de lo que se está tocando.
El código roto de ejemplo y la solución se pueden encontrar en el sitio de Paul Hudson.
https://www.hackingwithswift.com/forums/swiftui/unable-to-present-please-file-a-bug/7901/8237
A continuación se muestra la versión de trabajo completa
import SwiftUI struct NavigationViewOptions { enum OptionType { case main, optional } typealias Option = (id: UUID, value: String, type: Self.OptionType) static var options: [Option] = [ (UUID(), "Option 1", .main), (UUID(), "Option 2", .optional), (UUID(), "Option 3", .main), (UUID(), "Option 4", .main), (UUID(), "Option 5", .optional), ] static func buildView(for option: Option) -> some View { switch option.type { case .main: return Text("Main Option selected\n\(option.value)").font(.title).fontWeight(.bold) case .optional: return Text("Optional Option selected\n\(option.value)").font(.title3).italic().fontWeight(.medium) } } } struct NavigationViewWorking: View { // State variables to leep track of what option has been tapped on and when to navigate to new view @State private var selectedOption: NavigationViewOptions.Option = (id:UUID(),"",.main) @State private var showDetail: Bool = false var body: some View { NavigationView { ScrollView{ VStack (alignment:.leading) { Text("NAVIGATION FIX FOR:\nUnable to present. Please file a bug.") .padding(.bottom, 40) ForEach(NavigationViewOptions.options, id: \.id) { option in Text(option.value) .font(.title) .padding(.vertical, 10) .foregroundColor(.accentColor) // same color as navigationLink // handle tap on option .onTapGesture { selectedOption = option showDetail = true } } Spacer() NavigationLink("", destination: NavigationViewOptions.buildView(for: selectedOption), isActive: $showDetail) .opacity(0) } .navigationTitle("Options") } // INITIAL DETAIL VIEW Text("Select option from the left") } } }Parece que si hay más de un enlace de navegación en NavigationView, se archivará este error.
Aquí está mi solución.
import SwiftUI enum MyLink { case myView1 case myView2 } struct MyView1: View { var body: some View { Text("MyView1") } } struct MyView2: View { var body: some View { Text("MyView2") } } struct ExampleView: View { @State var currentLink: MyLink = .myView1 @State var isLinkViewShow: Bool = false func getLinkView(_ myLink: MyLink) -> some View { if myLink == .myView1 { return AnyView(MyView1()) } else { return AnyView(MyView2()) } } var body: some View { NavigationView { VStack { NavigationLink("", destination: getLinkView(currentLink), isActive: $isLinkViewShow) // Press to navigate to MyView1 Button(action: { currentLink = .myView1 isLinkViewShow = true }) { Text("To MyView1") } // Press to navigate to MyView2 Button(action: { currentLink = .myView2 isLinkViewShow = true }) { Text("To MyView2") } } } } }En Xcode13 beta todavía tiene este problema.
Hasta ahora solución:
1, Envuelva el enlace de navegación con la lista o el formulario:
List { NavigationLink(destination: Text("1")) { Text("1") } NavigationLink(destination: Text("2")) { Text("2") } NavigationLink(destination: Text("3")) { Text("3") } }2、O utilice un enlace de navegación y cree una vista de destino desde la función:
struct TaskIndexPage: View { func buildView() -> some View { // return you destination switch self.option { case 1: return Text("\(option)") default: return Text("\(option)") } } @State private var showDetail: Bool = false @State private var option: Int = 0 var body: some View { VStack { Button { showDetail = true option = 1 } label: { Text("button 1") } Button { showDetail = true option = 2 } label: { Text("button 2") } Button { showDetail = true option = 3 } label: { Text("button 3") } } // handle navigating NavigationLink(destination: self.buildView(), isActive: $showDetail) {}.opacity(0) } }Agregar un retraso hace que la navegación automática vuelva a funcionar.
NavigationLink(destination: PopupView(),isActive: $showView){}&
.onAppear { if (test()){ DispatchQueue.main.asyncAfter(deadline: .now() + 1) {showView = true} } }Para mí, la respuesta correcta no funcionó. Mostró Unable to present -message y luego la vista requerida fue presionada y apareció rápidamente. Mientras jugaba, encontré una solución que funcionaba. Mantengo los NotificationLink sin label establecidos como elementos de List simples.
NavigationView { ZStack { List { NavigationLink(isActive: $isFirstViewPresented, destination: firstView, label: EmptyView.init) NavigationLink(isActive: $isSecondViewPresented, destination: secondView, label: EmptyView.init) } .listStyle(.plain) //... Button("Show first view") { isFirstViewPresented.toggle() } Button("Show second view") { isSecondViewPresented.toggle() } } } No olvide envolver las propiedades activas con @State .
También tiene algunos beneficios para mí (todos los enlaces de navegación se colocan en la parte superior de la view -getter y no necesito buscarlos en todo el código.
Nunca pude encontrar una solución confiable para este horrible error. Así que decidí crear un NavigationLink personalizado, https://gist.github.com/Arutyun2312/a0dab7eecaa84bde99c435fecae76274 . Esto funciona mucho mejor de lo esperado, porque todas las funciones relacionadas con swiftui continúan funcionando como de costumbre. Parece que el error es específicamente con NavigationLink.
struct NavigationLink: View { fileprivate init<T: View>(body: T) { self.body = .init(body) } let body: AnyView } private struct NavigationLinkImpl<Destination: View, Label: View>: View { let destination: () -> Destination? @State var isActive = false @ViewBuilder let label: () -> Label var body: some View { NavigationLinkImpl1(destination: destination, isActive: $isActive, label: label) } } private struct NavigationLinkImpl1<Destination: View, Label: View>: View { let destination: () -> Destination @Binding var isActive: Bool @ViewBuilder let label: () -> Label @State var model = Model() var body: some View { Button(action: action, label: label) .introspectNavigationController(customize: handle) .id(isActive) } func handle(nav: UINavigationController) { if isActive { if model.destination == nil { let dest = UIHostingController<Destination>(rootView: destination()) nav.pushViewController(dest, animated: true) model.destination = dest } } else { if let dest = model.destination { if let i = nav.viewControllers.lastIndex(of: dest) { nav.setViewControllers(.init(nav.viewControllers.prefix(i + 1)), animated: true) } model.destination = nil } } if isActive != model.contains(nav: nav) { // detect pop isActive = model.contains(nav: nav) } } final class Model { var destination: UIHostingController<Destination>? func contains(nav: UINavigationController) -> Bool { destination.map { nav.viewControllers.contains($0) } ?? false } } func action() { isActive = true } } extension NavigationLink { init<Destination: View, Label: View>(destination: @autoclosure @escaping () -> Destination, @ViewBuilder label: @escaping () -> Label) { self.init(body: NavigationLinkImpl(destination: destination, label: label)) } init<Destination: View, Label: View>(destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>, @ViewBuilder label: @escaping () -> Label) { self.init(body: NavigationLinkImpl1(destination: destination, isActive: isActive, label: label)) } init<Destination: View>(_ text: String, destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>) { self.init(destination: destination(), isActive: isActive) { Text(text) } } init<Destination: View>(_ text: String, destination: @autoclosure @escaping () -> Destination) { self.init(destination: destination()) { Text(text) } } }Ponga esto en un archivo, y sus enlaces de navegación existentes funcionarán bien. Probado en ios 14 y 15