Reputation: 539
I'm new to swift and I cannot get the UserDefaults updated values in the same session. Only after the application restarts.
Here is what I mean in some code:
//This is where I have the userdefaults
@ObservedObject var userSettingsController = UserSettingsController
//These are the auxiliar vars I created to help me achieve the conditional renders I need. I'm looking to get rid of these and use the usersettings updated values
@State private var showMap = false
@State private var showTutorial = true
//Partial code of my view, where I'm using the variables
if(!self.userSettingsController.showActionSheet && self.showMap) {
showMapView()
.onTapGesture {
if (self.userSettingsController.showNextDeparturesTutorial && self.showTutorial {
self.showTutorial = false
self.userSettingsController.showNextDeparturesTutorial.toggle()
} else {
//code that has nothing to do with the question
No, here is my UserSettings and UserSettingsController classes:
UserSettings
import Foundation
struct UserSettings {
var settings: UserDefaults
init() {
self.settings = UserDefaults.standard
self.settings.register(
defaults: [
"userCity": "",
"showUserCityActionSheet": true,
"showNextDeparturesTutorial": true,
])
}
}
UserSettingsController
import Foundation
import Combine
import SwiftUI
class UserSettingsController: ObservableObject {
@Published var userSettings = UserSettings()
var userCity : String {
get {
return self.userSettings.settings.string(forKey: "userCity") ?? ""
}
set {
self.userSettings.settings.set(newValue, forKey: "userCity")
}
}
var showUserCityActionSheet: Bool {
get {
return self.userSettings.settings.bool(forKey: "showUserCityActionSheet")
}
set {
self.userSettings.settings.set(newValue, forKey: "showUserCityActionSheet")
}
}
var showNextDeparturesTutorial: Bool {
get {
return self.userSettings.settings.bool(forKey: "showNextDeparturesTutorial")
}
set {
self.userSettings.settings.set(newValue, forKey: "showNextDeparturesTutorial")
}
}
}
My question is, how can I get the updated values of the UserDefault values showNextDeparturesTutorial and showActionSheet in realtime? I've already tried to store them in other variables but to no avail.
Thanks.
EDIT
I accepted @Asperi answer because it was the most efficient one considering my project. However, @pawello2222 answer would also solve my problem.
Thanks, all.
Upvotes: 1
Views: 610
Reputation: 257563
The possible solution is to activate ObservableObject publisher explicitly in every setter, like below
var userCity : String {
get {
return self.userSettings.settings.string(forKey: "userCity") ?? ""
}
set {
self.userSettings.settings.set(newValue, forKey: "userCity")
self.objectWillChange.send() // << this one !!
}
}
Upvotes: 3
Reputation: 54436
You can make your variables @Published
. This way their changes will be detected by your View
.
Every time you modify some of these variables it will be saved to UserDefaults
as well. And when you init your UserSettingsController
you have to load values from UserDefaults
first:
class UserSettingsController: ObservableObject {
private let userSettings = UserDefaults.standard
@Published var showNextDeparturesTutorial: Bool {
didSet {
self.userSettings.set(showNextDeparturesTutorial, forKey: "showNextDeparturesTutorial")
}
}
init() {
_showNextDeparturesTutorial = .init(initialValue: userSettings.bool(forKey: "showNextDeparturesTutorial"))
}
}
struct ContentView: View {
@ObservedObject var userSettingsController = UserSettingsController()
...
}
Upvotes: 2
Reputation: 331
The problem is not the UserDefaults, it is that SwiftUI is not detecting any changes in the data since your data resides in the UserDefaults database and SwiftUI can’t see the changes.
The @Published on the userSettings variable is no use here since it is an object, and in the current version of SwiftUI/Combine, it only detects changes of the object being referenced, instead of changes within the object. E.g. if you assigned a different defaults object to UserDefaults it would fire its ObjectWillChange publisher.
You would be better off storing your settings values in actual variables, and using didSet to persist them to the User Defaults Database on each change. You would then only need to load them on startup to get the data back from User Defaults.
Upvotes: 1