Search code examples
xcodeswiftuionchangeequatable

Xcode on change not triggering


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


Solution

  • 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.