I have a custom preferences class and I would like to trigger a function whenever that is changed, at the moment it doesn't seem to work for some reason.
Here is the class
class Preferences: ObservableObject, Equatable{
static func == (lhs: Preferences, rhs: Preferences) -> Bool {
return lhs.email == rhs.email && lhs.password == rhs.password && lhs.faceID == rhs.faceID && lhs.currency == rhs.currency && lhs.colourScheme == rhs.colourScheme && lhs.appTheme == rhs.appTheme
}
@Published var email: String = ""
@Published var password: String = ""
@Published var faceID: Bool = false
@Published var currency: Currencies = .EUR
@Published var colourScheme: ColourScheme = .system
@Published var appTheme: Theme = .orange
This is stored in a viewmodel
class ViewModel: ObservableObject {
@Published var preferences = Preferences()
}
And here is the onchange call
.onChange(of: viewModel.preferences){ newValue in
viewModel.updateSettings(faceID: viewModel.preferences.faceID, currency: viewModel.preferences.currency, colourScheme: viewModel.preferences.colourScheme, appTheme: viewModel.preferences.appTheme)
}
The onchange never gets called? Any help would be appreciated. Thanks
Because preferences is an object there is no change, i.e. it is always the same object. SwiftUI is designed to work with value semantics, i.e. structs, so try making Preferences
a struct instead.
Also there is no need for that view model object, in SwiftUI the View struct is a view model already, which SwiftUI uses to create/update/remove UIView objects on screen. We use @StateObject
when we need a reference type in @State
, e.g. when doing something async, however the new .task
replaces that need.