SwiftUI presentationMode.wrappedValue.dismiss() pops back to root

Viewed 1002

In my project I'm trying to use the presentationMode.wrappedValue.dismiss() in SwiftUI to pop back to the previous view controller after saving data from a form.

The layout is like this:

Root Controller (with List View) --> List view --> Add New Data When using the dismiss() function it always pops back to the root controller instead of the List View.

Here is my code:

Root View Controller:

NavigationView {
            List {
                Section(header: Text("Sortiert nach \(sortStr)")) {
                        ForEach(dbModel.players) { player in
                            NavigationLink(destination: FeedbackListView(player: player)) {
                                PlayerListItemView(player: player)
                            }
                        }// ForEach
                        .onDelete(perform: delete)
                    }
            } // List
}

FeedbackListView

List {
            ForEach(dbModel.feedbacks) { feedback in
                FeedbackListItemView(feedback: feedback)
            }
            .onDelete(perform: delete)
        }//List
        .listStyle(GroupedListStyle())
        
        .toolbar(content: {
            ToolbarItem(placement: .navigationBarTrailing) {
                HStack(spacing: 16) {
                    
                    NavigationLink(destination: AddNewFeedbackView(forPlayer: player)) {
                        ToolbarPlusButton()
                    }//Add Button
                }
            }
        }) // Toolbar

AddNewFeedbackView

Form {
            Section(header: Text("Feedback für \(forPlayer.fullName)")) {
                TextField("Thema", text: $topic)
            }
            
            Section(header: Text("Inhalt")) {
                TextEditor(text: $coachingCue)
                    .frame(minHeight: 120)
            }
            
            Section(header: Text("Wichtigkeit")) {
                Picker(selection: $rating, label: Text("Wichtigkeit")) {
                    ForEach(0..<pickerContent.count) {
                        Text(self.pickerContent[$0])
                    }
                }//Picker
                .pickerStyle(SegmentedPickerStyle())
            }
            
            Section(header: Text("Datum")) {
                DatePicker("", selection: $date, in: ...Date())
                    .labelsHidden()
            }
            
            Section {
                Button(action: {
                    let secondsDate = date.timeIntervalSince1970
                    let newFeedback = Feedback(id: "", date: secondsDate, player: forPlayer.id!, rating: rating, topic: topic, coachingCue: coachingCue)
                    dbModel.addFeedback(newFeedback)
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Save")
                }
            }
        }
        .navigationBarTitle("Neues Feedback", displayMode: .inline)

When tapping the Save-Button I get sent back the Root Controller instead of the FeedbackListView.

1 Answers

I was experiencing the same thing. The origin in the problem is because the NavigationLink to AddNewFeedbackView is in an ToolbarItem. Why is this a problem? I don't know.

But after knowing this I found the following https://www.hackingwithswift.com/forums/swiftui/unexpected-behaviour-with-toolbar-and-navigation-bar/4893. Here it states that once you put the following navigation view style on your NavigationView it will be solved.

.navigationViewStyle(StackNavigationViewStyle())

So in your example it would result in:

NavigationView {
    List {
        Section(header: Text("Sortiert nach \(sortStr)")) {
            ForEach(dbModel.players) { player in
                NavigationLink(destination: FeedbackListView(player: player)) {
                    PlayerListItemView(player: player)
                }
            } // ForEach
            .onDelete(perform: delete)
        }
    } // List
}
.navigationViewStyle(StackNavigationViewStyle())
Related