无法实时获取 UserDefaults 更新值
Cannot get UserDefautls updated values in realtime
我是 swift 的新手,我无法在同一会话中获取 UserDefaults 更新值。仅在应用程序重新启动后。
这是我在一些代码中的意思:
//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
不,这是我的 UserSettings 和 UserSettingsController 类:
用户设置
import Foundation
struct UserSettings {
var settings: UserDefaults
init() {
self.settings = UserDefaults.standard
self.settings.register(
defaults: [
"userCity": "",
"showUserCityActionSheet": true,
"showNextDeparturesTutorial": true,
])
}
}
用户设置控制器
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")
}
}
}
我的问题是,如何实时获取 UserDefault 值 showNextDeparturesTutorial 和 showActionSheet 的更新值?我已经尝试将它们存储在其他变量中但无济于事。
谢谢。
编辑
我接受了@Asperi 的回答,因为考虑到我的项目,这是最有效的回答。
但是,@pawello2222 的回答也可以解决我的问题。
谢谢大家。
问题不在于 UserDefaults,而是 SwiftUI 未检测到任何数据更改,因为您的数据驻留在 UserDefaults 数据库中,而 SwiftUI 看不到更改。
userSettings变量上的@Published在这里没有用,因为它是一个对象,在SwiftUI/Combine的当前版本中,它只检测被引用对象的变化,而不是对象内部的变化.例如。如果您为 UserDefaults 分配了不同的默认对象,它将触发其 ObjectWillChange 发布者。
您最好将设置值存储在实际变量中,并在每次更改时使用 didSet 将它们保存到用户默认数据库中。然后,您只需在启动时加载它们即可从用户默认值中取回数据。
你可以让你的变量@Published
。这样,您的 View
.
就会检测到他们的更改
每次修改其中一些变量时,它也会保存到 UserDefaults
。当您初始化 UserSettingsController
时,您必须先从 UserDefaults
加载值:
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()
...
}
可能的解决方案是在每个 setter 中显式激活 ObservableObject 发布者,如下所示
var userCity : String {
get {
return self.userSettings.settings.string(forKey: "userCity") ?? ""
}
set {
self.userSettings.settings.set(newValue, forKey: "userCity")
self.objectWillChange.send() // << this one !!
}
}
我是 swift 的新手,我无法在同一会话中获取 UserDefaults 更新值。仅在应用程序重新启动后。
这是我在一些代码中的意思:
//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
不,这是我的 UserSettings 和 UserSettingsController 类:
用户设置
import Foundation
struct UserSettings {
var settings: UserDefaults
init() {
self.settings = UserDefaults.standard
self.settings.register(
defaults: [
"userCity": "",
"showUserCityActionSheet": true,
"showNextDeparturesTutorial": true,
])
}
}
用户设置控制器
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")
}
}
}
我的问题是,如何实时获取 UserDefault 值 showNextDeparturesTutorial 和 showActionSheet 的更新值?我已经尝试将它们存储在其他变量中但无济于事。
谢谢。
编辑
我接受了@Asperi 的回答,因为考虑到我的项目,这是最有效的回答。 但是,@pawello2222 的回答也可以解决我的问题。
谢谢大家。
问题不在于 UserDefaults,而是 SwiftUI 未检测到任何数据更改,因为您的数据驻留在 UserDefaults 数据库中,而 SwiftUI 看不到更改。
userSettings变量上的@Published在这里没有用,因为它是一个对象,在SwiftUI/Combine的当前版本中,它只检测被引用对象的变化,而不是对象内部的变化.例如。如果您为 UserDefaults 分配了不同的默认对象,它将触发其 ObjectWillChange 发布者。
您最好将设置值存储在实际变量中,并在每次更改时使用 didSet 将它们保存到用户默认数据库中。然后,您只需在启动时加载它们即可从用户默认值中取回数据。
你可以让你的变量@Published
。这样,您的 View
.
每次修改其中一些变量时,它也会保存到 UserDefaults
。当您初始化 UserSettingsController
时,您必须先从 UserDefaults
加载值:
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()
...
}
可能的解决方案是在每个 setter 中显式激活 ObservableObject 发布者,如下所示
var userCity : String {
get {
return self.userSettings.settings.string(forKey: "userCity") ?? ""
}
set {
self.userSettings.settings.set(newValue, forKey: "userCity")
self.objectWillChange.send() // << this one !!
}
}