I have a class that I cannot change to ObservableObject with Published members.
I tried getting around this by writing my own Binding. Although the value is updated correctly, the UI is not. Why is this.
Below is a simple demo view. When it is run and the toggle is clicked, it will print out correctly that the value is changed, but the UI does not update. Why?
import SwiftUI
class BoolWrapper {
public var value = false {
didSet {
print("Value changed to \(value)")
}
}
}
let boolWrapper = BoolWrapper()
struct ContentView: View {
var body: some View {
Toggle(isOn: Binding(get: {
return boolWrapper.value
}, set: { value in
boolWrapper.value = value
}), label: { Text("Toggle") })
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Why can't you add the ObservableObject
protocol conformance? It only really affects the properties that are marked with the @Published
property wrapper, i.e. the properties that update the UI. This is what allows SwiftUI to update the UI based on properties in a class – it is the recommended way.
class BoolWrapper: ObservableObject {
@Published var value = false {
didSet {
print("Value changed to \(value)")
}
}
}
struct ContentView: View {
@StateObject private var boolWrapper = BoolWrapper()
var body: some View {
Toggle("Toggle", isOn: $boolWrapper.value)
}
}
The UI can't update if it doesn't watch for changes from inside a class. That is why ObservableObject
exists in SwiftUI.
If it was a struct, you would only need to use an @State
property due to the nature of structs (vs classes).