0

I am having trouble using an @EnvironmentObject in an @ObservableObject class. Based on some research, this is not possible, as EnvironmentObject is for views only.

I have resorted to doing the following, but the value is not updated dynamically.

For example, it is initialized with the value of "A", but when I change the value in a class that is using EnvironmentObject, the value found in my ObservableObject class remains "A". It updates in all other locations that are using the @EnvironmentObject, just not the ObservableObject API class.

Is there a way to have the code in the ObservableObject API class update when the EnvironmentObject updates the published variable?

The class that needs a variable in it that operates like EnvironmentObject is the API class.

class SelectedStation: ObservableObject {
    @Published var selectedStation: String = "A"
}

    class API: ObservableObject {
        
        var selectedStation: SelectedStation
    
        init(selectedStation: SelectedStation) {
                self.selectedStation = selectedStation
            print(selectedStation.selectedStation)
            
            }
///some code that will utilize the selectedStation variable
}

What exactly am I doing wrong here?

1 Answer 1

1

You are initializing a different version of your class. Try adding public static let shared = SelectedStation() like this:

class SelectedStation: ObservableObject {
    @Published var selectedStation: String = "A"
    public static let shared = SelectedStation()
}

and then where you need to use it, declare it as:

var selectedStation = SelectedStation.shared

Also, you should rename the @Published var to something other than selectedStation, otherwise you could run into the unfortunate selectedStation.selectedStation as a reference to that variable.

Lastly, remember the @Environment needs to be initialized with the SelectedStation.shared so everything is sharing the one instantiation of the class.

Sign up to request clarification or add additional context in comments.

4 Comments

This works flawlessly. Thank you! And I agree, I need to change the naming here, as selectedStation.selectedStation is far from ideal. Lastly, does this sort of design pattern have a name?
It is essentially, but not exactly, a Singleton pattern. A true Singleton can only ever have one instantiation, which is not true here, but so long as you use the .shared it is effectively a Singleton. It is very useful for your single source of truth when you need to use it in a non-view.
Got it. Now is there any reason to have this stored in an ObservableObject class? Since this is just a public variable, it seems like I can place the public static let shared = SelectedStation() anywhere I want. Or is that an incorrect assumption?
If it is not @Published, you won't get your view updated when it changes. That only exists in an ObservableObject class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.