iosswiftswiftdataswiftui-navigationsplitview

SwiftUI NavigationSplitView does not change detail/destination


The detail view / the destination of the NavigationSplitView does not change when selecting another item in the sidebar.

Given a Swift Data Model

@Model final class MyModel {
    var text: String
    init(text: String) {self.text = text}
}

And a NavigationSplitView, that should display all of those models plus an edit view

struct MyModelEditView: View {
    @Environment(\.modelContext) var modelContext
    @State var myModel: MyModel
    var body: some View {
       TextField("Edit Text", text: $myModel.text)
    }
}
 
struct ContentView: View {
    @Environment(\.modelContext) var modelContext
    @Query var models: [MyModel]
    var body: some View {
        NavigationSplitView {
           List {
               ForEach(myModels) { model in
                   NavigationLink {
                      MyModelEditView(myModel: model)
                          .modelContext(modelContext)
                   } label: {
                       Text(model.text)
                   }
               }
           }
        } detail: {
            Text("Tap plus for a new model")
        }
        // we pretend that here is a button in a toolbar that adds a new model
    }       

When initially clicking on any item in the list, the detail view for this item is displayed! But when clicking on another model, the detail view just stays where it was, with the previous model.

I also tried to create an @State var selectedModel: MyModel and using the List initializer List(selection: $selectedModel) , tagging each item in the ForEach (.tag(model)) instead of using NavigationLink and then in the detail block:

detail: {
    if let selectedModel {
        MyModelEditView(myModel: myModel)
            .modelContext(modelContext)
    } else {
Text("Tap plus for a new model")
    }
}

... But also this did not help.

I've found out that .navigationDestination(for:) is limited to NavigationStack, so I am left with no idea how to make a working Navigation Stack for my SwiftData models.

! Note that this is not specific to SwiftData models as objects, this does also happen with any Kind of structs or classes, I tried it with a struct containing just a single String such as the MyModel class.


Solution

  • As suggested in the comments, @Bindable will fix the issue without having to use another view modifier.

    struct MyModelEditView: View {
        @Bindable var myModel: MyModel
        var body: some View {
           TextField("Edit Text", text: $myModel.text)
        }
    }