0

I have implemented a navigation stack and enum following https://stackoverflow.com/a/74362840/21094465 yet I am still receiving the following "A navigationDestination for AppExample.GreaterViewOptions was declared earlier on the stack. Only the destination declared closest to the root view of the stack will be used" when I navigate past the second view.

My enum

enum GreaterViewOptions {
    case whatIsNewView
    case contentView
    case setUpStart
    case setUpStepOne
    case setUpStepTwo
    case connectionSuccessful
    case firmwareUpdateView
    case registerView
    @ViewBuilder func view(_ path: Binding<NavigationPath>) -> some View{
               switch self{
               case .whatIsNewView:
                   WelcomeScreenView(path: path)
               case .contentView:
                   ContentView(path: path).environmentObject(SheetManager())
               case .setUpStart:
                   SetupGuideSearchView(path: path)
               case .setUpStepOne:
                   SetupGuideConnectionStepOneView(path: path)
               case .setUpStepTwo:
                   SetupGuideConnectionStepTwoView(path: path)
               case .connectionSuccessful:
                   ConnectionSuccessfulView(path: path)
               case .firmwareUpdateView:
                   FirmwareUpdateView(path: path)
               case .registerView:
                   RegisterView(path: path)
               }
           }
}

and like I saw, I'm calling it by appending to the path as follows:

  Button(action: {
            path.append(GreaterViewOptions.whatIsNewView)
        }) {
            Text("CONTINUE")
                .foregroundColor(.white)
        }

and so my sequence of views goes as follows (just the first couple)

Initial View

struct BumperScreen: View {
    
    init(viewModel: @autoclosure @escaping () -> BumperScreenViewModel) {
        self._viewModel = .init(wrappedValue: viewModel())
    }
    
    var body: some View {
        NavigationStack(path: $path) {
                ZStack {
                    Color(.trulliGold)
                        .ignoresSafeArea()
                    VStack {
                        if show {
                            Spacer()
                            loadAnimation
                                .frame(width: 150, height: 150)
                                .task {
                                    try? await viewModel.getDataFromAPI()
                                    try? await Task.sleep(for: Duration.seconds(1))
                                    doneLoading.toggle()
                                    show.toggle()
                                    path.append(GreaterViewOptions.contentView)
                                }
                            Spacer()
                            
                        } else {
                            launchAnimation
                        }
                    }
                }
                .navigationDestination(for: GreaterViewOptions.self) { option in
                    option.view($path)
                }
        }
    }

which brings us to our list of policies that you have to check:

struct ContentView: View {
    @EnvironmentObject var sheetManager: SheetManager
    
    var body: some View {

            ZStack {
                Color(.trulliGold)
                    .ignoresSafeArea()
                VStack {

                    Spacer()
                    headerStatement
                    Spacer()
                    VStack {
                        privacyPolicy
                        bluetoothPolicy
                        locationsPolicy
                        notificationsPolicy
                        apprunningPolicy
                    }
                    Spacer()
                    Spacer()
                    continueButton
                }
            }
            .popup(with: sheetManager)
        .navigationBarBackButtonHidden()
    }
}

var continueButton: some View {
        Button(action: {
            path.append(GreaterViewOptions.whatIsNewView)
        }) {
            Text("CONTINUE")
                .foregroundColor(.white)
        }
        .disabled(!self.areAllChecked)
        .padding()
        .background(Color.orange)
        .foregroundColor(.white)
        .clipShape(Capsule())
        .padding(.bottom, 32)
    }

There's no warning from the BumperScreen to ContentView, but there is the warning I said earlier from ContentView to the third view and views thereafter.

struct WelcomeScreenView: View {    
    var body: some View {
            ZStack {
                Color(.gold)
                    .ignoresSafeArea()
                VStack(alignment: .center, spacing: 8) {
                    
                    header
                    Spacer()
                    tabView
                    Spacer()
                    Spacer()
                    nextButton
                    closeButton
                }
            }
        .navigationBarBackButtonHidden(true)
    }
}

I've tried adding the navigationDestination modifier to the Content and Welcome views but the app keeps being sent back to the BumperScreen, leading me to believe that way is wrong.

kenada97
  • 19
  • 3

1 Answers1

0

Remove the enum, @ViewBuilder and view model. Use a navigationDestination per model value. Don't try to put view structs in the navigation path.

malhal
  • 26,330
  • 7
  • 115
  • 133
  • I'm not sure if I quite understand what you're suggesting. Could you be more specific or offer some pieces of code showing what you mean? – kenada97 Mar 13 '23 at 12:30