@Observation: Best way of handling binding after injecting a View-Model

In WWDC 2023 there was a good summary of how to handle the iOS 17 Observation capability.

But despite the clear graphics, it was still ambiguous (for me.) I want to inject a class (view-model) so that it can be used in the complete view heirarchy, and used in bindings to allow bi-directional communication.

As far as I can tell there are 2 ways of declaring the VM (alternatives 1 and 2 in my code), and 2 ways of consuming the VM in a view (alternatives 3 and 4 in my code). Using the flow-diagram I can't determine which is best.

Here's the crux of my #Observable problem.

import SwiftUI

// MARK: - Model
struct MyMod {
    var title = "Hello, World!"
}

// MARK: - MVV
@Observable
class MyMVV {
    var model: MyMod
    init() {
        self.model = MyMod()
    }
}

// MARK: - App
@main
struct MyApp: App {
    @Bindable var myGlobalMVV = MyMVV()                                      // Alternative 1
 // @State    var myGlobalMVV = MyMVV()                                      // Alternative 2
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(myGlobalMVV)                                    // inject
        }
    }
}

struct ContentView: View {
    
    var body: some View {
        ContentDeepHierarchyView()
    }
}
    
struct ContentDeepHierarchyView: View {
    @Environment(MyMVV.self) var myGlobalMVV                                  // digest
    
    var body: some View {
        @Bindable var myLocalMVV = myGlobalMVV                                // Alternative 3
        
        TextField("The new title", text: $myLocalMVV.model.title)             // Alternative 3
        TextField("The new title", text: Bindable(myGlobalMVV).model.title)   // Alternative 4
    }

Opinions?

Answered by Alanrick in 816775022

I've researched. The diagram is a slight oversimplification. Alternative 2 (@State) is the correct answer.

Accepted Answer

I've researched. The diagram is a slight oversimplification. Alternative 2 (@State) is the correct answer.

@Observation: Best way of handling binding after injecting a View-Model
 
 
Q