Correctly initializing observable classes in modern SwiftUI

I have two @Observable manager classes, which share a reference to a third class. I initialize this setup using a custom init in my App struct, like so:

@main
struct MyApp: App {    
    private let managerA: ManagerA
    private let managerB: ManagerB
    
    init() {
        let managerC = ManagerC()
        self.managerA = ManagerA(managerC: managerC)
        self.managerB = ManagerB(managerC: managerC)
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(managerA)
                .environment(managerB)
        }
    }
}

I've been using this pattern for some time and it has been working fine. However, I just today discovered that @Observable objects are supposed to be initialized as @State vars, as shown in Apple's documentation here. This means I shoud be doing the following:

@main
struct MyApp: App {    
    @State private var managerA: ManagerA
    @State private var managerB: ManagerB
    
    init() {
        let managerC = ManagerC()
        self.managerA = ManagerA(managerC: managerC)
        self.managerB = ManagerB(managerC: managerC)
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(managerA)
                .environment(managerB)
        }
    }
}

I've also seen some examples where the @State vars are initialized manually like this:

@main
struct MyApp: App {    
    @State private var managerA: ManagerA
    @State private var managerB: ManagerB
    
    init() {
        let managerC = ManagerC()
        let managerA = ManagerA(managerC: managerC)
        let managerB = ManagerB(managerC: managerC)
        
        self._managerA = State(initialValue: managerA)
        self._managerB = State(initialValue: managerB)
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(managerA)
                .environment(managerB)
        }
    }
}

ChatGPT tells me the third approach is the correct one, but I don't understand why and ChatGPT can't produce a convincing explanation. The compiler doesn't produce any errors or warnings under each approach, and as far as I can tell, they all behave identically with no discernible difference in performance.

Does it matter which pattern I use? Is there a "correct" way?

If you’re performing any significant work on your state’s default value or instantiating Observable objects, we recommend handling that differently for optimal performance.

For example:

struct MyView: View {
    @State private var object = MyObject()

    var body: some View {
        ContentView(object)
    }
}

That's not the best for performance, because MyObject will be instantiated eagerly every time MyView is initialized, which is expensive since it allocates a new object,

Instead defer the creation of the object using callbacks like, ,task, .onAppear or .onChange(of:). For example:

struct MyView: View {
    @State private var object: MyObject?

    var body: some View {
        ContentView(object)
            .task { object = MyObject() }
    }
}

If the model needs to be part and owned by the view, then use @State. If the model needs to be global to your appliction use @Environment. Please review WWDC23 Session: Discover Observation in SwiftUI and Managing model data in your app

Thanks for getting back to me.

I'm thinking specifically about the instantiation of a manager-style class that is global to the app and placed into the environment at launch time. The documentation that you linked to gives this specific example:

@main
struct BookReaderApp: App {
    @State private var library = Library()

    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }
    }
}

In the example, the Library class is created as a @State var and put into the environment. My first question (which is more theoretical) is: Why does the variable need to be annotated with @State. My (perhaps naive) assumption was that the App struct is special and is initialized only once, so it's not immediately obvious to me why its properties need to be held in state. Indeed, making it a let constant without the @State annotation seems to result in the same behavior.

My second, more practical question is: What is the correct way to manually instantiate the Library (rather than doing so in the property declarations). There are various reasons why you might want to do this, but for the sake of example, I'm thinking of something along these lines:

@main
struct BookReaderApp: App {
    @State private var library

    init() {
        let thing = Thing()
        self.library = Library(thing: thing)
    }

    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }
    }
}

Note that in this case, Library is not created in the property declarations, but in the init. Searching around on GitHub, I find some examples where people do:

self.library = Library(thing: thing)

and other cases where people do:

self._library = State(initialValue: Library(thing: thing))

I'm trying to understand what the difference is between these two (if anything).

Thanks for any light you can shed on these (possibly newbie) questions!

Correctly initializing observable classes in modern SwiftUI
 
 
Q