SwiftUI NavigationView trying to pop to missing destination (Monoceros?)
Asked Answered
P

2

29

I'm using Xcode 12 with deployment for iOS 14.0.

  • My home screen has a NavigationView
  • Within the NavigationView there is a TabView (with 4 tabs)
  • Within each tab are subviews that have buttons and NavigationLinks

The navigation on the app is functioning correctly (when I click a NavigationLink on one of the subviews, it navigates to the correct view and when I click the back button, it dismisses the view.) However, when I click the back button, the console prints the following error:

Trying to pop to a missing destination at /Library/Caches/com.apple.xbs/Sources/Monoceros/Monoceros-103/Shared/NavigationBridge_PhoneTV.swift:337

Aside from the error log, the app is functioning fine, so I'm planning to just ignore the error for now... but I'm wondering what it means? I don't have anything within my code named "Monoceros". I'm guessing it has something to do with the TabView being a subview of the NavigationView?

EDIT:

Several months later, this issue still persists. Here is reproducible code. Open the ContentView(), on the FirstScreen() click on the NavigationLink, then click the back button. It will print out Monoceros lol

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            TabView {
                FirstScreen()
                    .tabItem {
                        Text("One")
                        Image(systemName: "house.fill")
                    }
                
                Text("Second Screen")
                    .tabItem {
                        Text("Two")
                        Image(systemName: "heart.fill")
                    }
            }
        }
    }
}

struct FirstScreen: View {
    var body: some View {
        NavigationLink("Click here", destination: Text("Final Screen"))
        // Click the back button on FinalScreen prints:
        //Trying to pop to a missing destination at /Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-120/Shared/NavigationBridge_PhoneTV.swift:341
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Passim answered 29/9, 2020 at 17:15 Comment(6)
Did you solved it ?Disequilibrium
Nope. I think it's because the TabView is a subview of the NavigationView. If you instead add the NavigationView as a subview within the TabView, the error goes away. However, that changes the UI and didn't work for us. We ended up just ignoring the error and publishing to the App Store. To my knowledge, the error hasn't caused any issues.Passim
Can you provide a reproducible example?Broome
@Broome Updated. ThanksPassim
@Passim have you been able to resolve the error message being thrown? I am encountering the exact same issue with your exact same usecase... I dont mind the error but dont want to be rejected by apple when submitting app!?Mcarthur
@Mcarthur No I haven't resolved it but this shouldn't cause you to be rejected.Passim
V
15

Unfortunately this is an active issue with a TabView placed inside NavigationView.

The error would not manifest itself if you placed your NavigationView inside the TabView, but this of course would lead to the tabs being displayed from within your Final Screen, which you are probably trying to avoid.

                                      enter image description here

There is currently no work-around for this, and as of to date we need to wait for Apple to properly implement the corresponding .navigationBarHidden() of TabViews as well.

Problems and unexpected behaviours have been reported when embedding a TabView into a NavigationView, however if you have tested your app thoroughly and found no particular problems, it is safe to say that you can stick to this method.

Alternatively you will have to build a TabView component manually, like below:

import SwiftUI


enum Tab {
    case house, heart
}

struct TabView: View {
    @Binding var tabIdx: Tab
    
    var body: some View {
        HStack {
            Group {
                Spacer()
                
                Button (action: {
                    self.tabIdx = .house
                }) {
                    VStack{
                        Image(systemName: "house.fill")
                        Text("House")
                            .font(.system(size: 10))

                    }
                }
                .foregroundColor(self.tabIdx == .house ? .blue : .secondary)
                
                Spacer()
                
                Button (action: {
                    self.tabIdx = .heart
                }) {
                    VStack{
                        Image(systemName: "heart.fill")
                        Text("Heart")
                            .font(.system(size: 10))

                    }
                }
                .foregroundColor(self.tabIdx == .heart ? .blue : .secondary)
                
                Spacer()
            }
        }
        .padding(.bottom, 30)
        .padding(.top, 10)
        .background(Color(red: 0.1, green: 0.1, blue: 0.1))
        .font(.system(size: 30))
        .frame(height: 80)
    }
}

struct FirstScreen: View {
    var body: some View {
        NavigationLink("Click here", destination: Text("Final Screen"))
            .font(.system(size:20))
    }
}

struct ContentView: View {
    @State var tabIdx: Tab = .house
    
    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Spacer()
                if tabIdx == .house {
                    FirstScreen()
                } else if tabIdx == .heart {
                    Text("Second Screen")
                }
                Spacer(minLength: 0)
                TabView(tabIdx: self.$tabIdx)
            }
            .ignoresSafeArea()

        }
    }

}

The above bug is well detailed in this blog post, which you could consult for further reference and more examples.

Vittoria answered 4/3, 2021 at 18:45 Comment(1)
This solved it for me. Although I decided to follow a different tutorial to create a custom tabView. youtube.com/watch?v=FxW9Dxt896USoil
V
1

Update in 2023. Apparently NavigationView is deprecated and you should use NavigationStack for iOS16. Simply change NavigationView to NavigationStack and the warning will go away! You can still keep all your navigation links. Also with this change, my navigationTitle and navigationDisplayMode .inline started working in my TabItems.

struct ContentView: App {
@State var selection = 1

var body: some Scene {
WindowGroup {
    NavigationStack {
        TabView(selection: $selection) {
            GridView()
                .tabItem {
                    Label("Study", systemImage: "book")
                        .symbolRenderingMode(.hierarchical)
                }
                .tag(1)
            
            StudyView()
                .tabItem {
                    Label("Test", systemImage: "graduationcap")
                }
                .tag(2)
        }
        .navigationTitle(selection == 1 ? "Study a Language" : "Take a Test")
      }
   }
}
Vocoid answered 21/9, 2023 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.