ios – Read SwiftUI environmentObject outside view hierarchy


I need to access variables from the EnvironmentObject in plain (non-view) Swift classes–just read them, not update them (all updates occur within views). I’ve read in a few answers such as here and here that making your environment object a singleton works well for this. Does this look like a valid way to do it?

It definitely works, I’m just worried there is something about the approach that could break the management of the publishing. I know that updating the variables via the shared instance would break the publishing, but if you’re just reading values, should this be OK?

PROBLEM CODE

class AppViewModel: ObservableObject {
    @Published var lastName = ""
}

struct MyApp: App {
    @StateObject var appViewModel = AppViewModel()
    
    var body: some Scene {
        WindowGroup {
            MainView()
            .environmentObject(appViewModel)
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var myAppViewModel: AppViewModel
    
    var body: some View {
        TextField("enter last name", text: $myAppViewModel.lastName)
    }
}

class PlainSwiftClass {
    @EnvironmentObject var appViewModel: AppViewModel // <-- DOESN'T WORK, NOT A VIEW
    func getLastName() {
        print(appViewModel.lastName)
    }
}

SUGGESTED FIX

class AppViewModel: ObservableObject {
    static let shared = AppViewModel() // <-- Adding shared instance

    @Published var lastName = ""
}

struct MyApp: App {
    @StateObject var appViewModel = AppViewModel.shared // <-- Instantiating from the shared instance

    var body: some Scene {
        WindowGroup {
            MainView()
            .environmentObject(appViewModel)
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var myAppViewModel: AppViewModel

    var body: some View {
        // No changes here. You can still update the @StateObject as before.
        TextField("enter last name", text: $myAppViewModel.lastName) 
    }
}
class PlainSwiftClass {
    func getLastName() {
        print(AppViewModel.shared.lastName) // <--- THIS WORKS
    }
}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img