I have the following simple SwiftUI view which contains a component containing a list of marketing preference options with checkboxes and a button to update the preferences:
@StateObject var marketingPreferencesViewModel: MarketingPreferencesViewModel
var body: some View {
VStack {
MarketingPreferencesView(viewModel: .init())
Button {
marketingPreferencesViewModel.marketingUpdateRequested()
} label: {
Text("Update prefs")
}
}
}
MarketingPreferencesView is as follows:
struct MarketingPreferencesView: View {
@ObservedObject var viewModel: MarketingPreferencesViewModel
var body: some View {
VStack(alignment: .leading) {
marketingPreference(type: .email)
marketingPreference(type: .directMail)
marketingPreference(type: .notification)
marketingPreference(type: .sms)
marketingPreference(type: .telephone)
}
}
func marketingPreference(type: MarketingOptions) -> some View {
HStack {
if viewModel.preferencesAreLoading {
ProgressView()
} else {
Button {
switch type {
case .email:
viewModel.emailMarketingEnabled.toggle()
case .notification:
viewModel.notificationMarketingEnabled.toggle()
case .sms:
viewModel.smsMarketingEnabled.toggle()
case .telephone:
viewModel.telephoneMarketingEnabled.toggle()
case .directMail:
viewModel.directMailMarketingEnabled.toggle()
}
} label: {
switch type {
case .email:
viewModel.emailMarketingEnabled ? Image.General.Checkbox.checked : Image.General.Checkbox.unChecked
// ... remaining switch cases follow same pattern
}
}
}
Text(type.title())
}
.padding(.bottom, Constants.bottomPadding)
}
}
And the MarketingPreferencesViewModel:
class MarketingPreferencesViewModel: ObservableObject {
@Published var emailMarketingEnabled = false {
didSet {
print(emailMarketingEnabled)
}
}
@Published var directMailMarketingEnabled = false
@Published var notificationMarketingEnabled = false
@Published var smsMarketingEnabled = false
@Published var telephoneMarketingEnabled = false
private func updateMarketingPreferences() {
// For now, just printing emailMarketingEnabled value for debugging
print(emailMarketingEnabled)
}
func marketingUpdateRequested() {
self.updateMarketingPreferences()
}
}
}
So the user taps on the marketing preference button, this toggles the corresponding value in the view model.
However, for some reason when I hit the marketingUpdateRequested() method, if I check the value of emailMarketingEnabled, it is always false even if I have toggled it already.
Steps to reproduce:
- Tap on the emailMarketingEnabled button
- 'true' is printed in the console
- tap on the 'Update prefs' button
- 'false' is printed
I have placed the didSet on the emailMarketingEnabled property to see if it changes elsewhere, and it does not. Why then, once I have set to true, is this then false when I tap the button?
CodePudding user response:
You need to instantiate the MarketingPreferencesViewModel
, then pass it to your
MarketingPreferencesView
, like in the following example code:
// -- here
@StateObject var marketingPreferencesViewModel = MarketingPreferencesViewModel()
var body: some View {
VStack {
MarketingPreferencesView(viewModel: marketingPreferencesViewModel) // <-- here
Button {
marketingPreferencesViewModel.marketingUpdateRequested()
} label: {
Text("Update prefs")
}
}
}