Categories
ios swift swiftui

SwiftUI: observe @Environment property changes

I was trying to use the SwiftUI @Environment property wrapper, but I can’t manage to make it work as I expected. Please, help me understanding what I’m doing wrong.

As an example I have an object that produces an integer once per second:

class IntGenerator: ObservableObject {
@Published var newValue = 0 {
didSet {
print(newValue)
}
}
private var toCanc: AnyCancellable?
init() {
toCanc = Timer.TimerPublisher(interval: 1, runLoop: .main, mode: .default)
.autoconnect()
.map { _ in Int.random(in: 0..<1000) }
.assign(to: \.newValue, on: self)
}
}

This object works as expected since I can see all the integers generated on the console log. Now, let’s say we want this object to be an environment object accessible from all over the app and from whoever. Let’s create the related environment key:

struct IntGeneratorKey: EnvironmentKey {
static let defaultValue = IntGenerator()
}
extension EnvironmentValues {
var intGenerator: IntGenerator {
get {
return self[IntGeneratorKey.self]
}
set {
self[IntGeneratorKey.self] = newValue
}
}
}

Now I can access this object like this (for example from a view):

struct TestView: View {
@Environment(\.intGenerator) var intGenerator: IntGenerator
var body: some View {
Text("\(intGenerator.newValue)")
}
}

Unfortunately, despite the newValue being a @Published property I’m not receiving any update on that property and the Text always shows 0. I’m sure I’m missing something here, what’s going on? Thanks.