Reputation: 9660
I have a following scenario.
I have AppState which consists of an object of type Foo. Foo has a counter variable and I want to call objectWillChange when counter value updates so I can update the UI.
At present nothing happens. The increment function gets called but the UI never gets updated.
import Foundation
import Combine
class Foo: ObservableObject {
@Published var counter: Int = 999
func increment() {
counter += 1 // how to get notified when counter value changes
}
}
class AppState: ObservableObject {
@Published var foo: Foo = Foo()
}
// usage in Scene Delegate as Environment Object
let appState = AppState()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: accountSummaryScreen.environmentObject(appState))
UPDATE
class Foo: ObservableObject {
@Published var counter: Int = 999 {
didSet {
objectWillChange.send()
}
}
func increment() {
counter += 1 // how to get notified when counter value changes
}
}
Upvotes: 3
Views: 1645
Reputation: 30582
In SwiftUI our model types are structs, e.g.
struct Foo: Identifiable {
let id = UUID()
var counter: Int = 999
mutating func increment() {
counter += 1
}
}
Now it can be used with @Published
in an ObservableObject
.
Upvotes: 1
Reputation: 49590
Changes aren't detected because Foo
, being a reference-type, doesn't actually change - it's the same reference, so @Published
doesn't help here.
AppState
would need to manually subscribe to changes and call its own objectWillChange.send
:
class AppState: ObservableObject {
var foo: Foo = Foo() {
didSet {
cancellables = []
foo.$counter
.map { _ in } // ignore actual values
.sink(receiveValue: self.objectWillChange.send)
.store(in: &cancellables)
}
}
private var cancellables: Set<AnyCancellable> = []
}
Upvotes: 3