0

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

Cian B
  • 31
  • 6
  • Does this answer your question? [SwiftUI View updating](https://stackoverflow.com/questions/68710726/swiftui-view-updating) – lorem ipsum Nov 18 '22 at 19:23
  • No, I don't see how that answers my question. My problem is that the onchange function isn't triggering, even though my preferences is set to Equatable. – Cian B Nov 18 '22 at 19:46
  • It wouldn’t because you aren’t observing the object. It needs to be wrapped as well. Every observable object needs a wrapper in a SwiftUI view – lorem ipsum Nov 18 '22 at 19:49
  • And how would i go about doing that. Sorry for my ignorance – Cian B Nov 18 '22 at 20:03
  • Look at the link it has the different layers – lorem ipsum Nov 18 '22 at 20:09
  • Sorry, I don't know what part I'm meant to be looking at? Is there anyway you could explain the solution in relation to my question? Sorry for the inconvenience. – Cian B Nov 18 '22 at 20:18
  • The program is your view model and the exercise is your preference. It is the same concept. – lorem ipsum Nov 18 '22 at 21:51

1 Answers1

0

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.

malhal
  • 26,330
  • 7
  • 115
  • 133
  • A `struct` is probably better for this scenario but `Preferences` is not much different than a Core Data object. Apple has many samples where they use view models in their code. – lorem ipsum Nov 18 '22 at 21:54