How to reuse view model instance for destination view in a NavigationLink

Apologies, my code is adapted from yours as I've not updated to the latest beta yet, but this works for me. I've used the concept of "Lifting State Up" from React, and moved the model data into the Master view itself.

From a playground:

import SwiftUI
import PlaygroundSupport


final class ItemViewModel : BindableObject {
    let willChange = PassthroughSubject<Void, Never>()

    var name: String {
        willSet { willChange.send() }
    }
    var counter: Int = 0 {
        willSet { willChange.send() }
    }

    init(name: String) {
        self.name = name
    }
}


struct ContentView : View {
    let items = [
        ItemViewModel(name: "Item A"),
        ItemViewModel(name: "Item B"),
        ItemViewModel(name: "Item C")
    ]

    @State var contentViewUpdater = 0

    var body: some View {
        NavigationView {
            VStack {
                Button("Update ContentView: \(contentViewUpdater)") {
                    self.contentViewUpdater += 1
                }
                List(items) { model in
                    NavigationLink(destination: DetailView(model: model)) {
                        Text(model.name)
                    }
                }
            }
        }
    }
}


struct DetailView : View {
    @ObjectBinding var model: ItemViewModel

    var body: some View {
        let name = model.name
        let counter = model.counter
        return VStack {
            Text("Counter for \(name): \(counter)")
            Button("Increase counter") {
                self.model.counter += 1
            }
        }
    }
}


PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
PlaygroundPage.current.needsIndefiniteExecution = true

Screen recording from Playground

Tags:

Ios

Swift

Swiftui