无法实时获取 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 !!
    }
}