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?

nickreps
  • 903
  • 8
  • 20

1 Answers1

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.

Yrb
  • 8,103
  • 2
  • 14
  • 44
  • 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? – nickreps Jul 25 '21 at 22:26
  • 1
    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. – Yrb Jul 25 '21 at 22:32
  • 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? – nickreps Jul 25 '21 at 22:36
  • If it is not `@Published`, you won't get your view updated when it changes. That only exists in an `ObservableObject` class. – Yrb Jul 25 '21 at 22:41