【问题标题】:Best way to use UserDefaults with ObservableObject in Swiftui在 Swiftui 中使用 UserDefaults 和 ObservableObject 的最佳方式
【发布时间】:2025-12-18 09:55:01
【问题描述】:

我正在尝试将用户基本数据保存在 UserDefaults 中。

我的目标是能够使用来自 UserDefaults 的数据,以便在用户每次进行一些更改时更新它们。

我正在使用 ObservableObject 类来设置和获取这些数据

class SessionData : ObservableObject {
    @Published var loggedInUser: User = User(first_name: "", last_name: "", email: "")
    static let shared = SessionData()

    func setLoggedInUser (user: User) {
        let encoder = JSONEncoder()
        if let encoded = try? encoder.encode(user) {
            UserDefaults.standard.set(encoded, forKey: "User")
            self.loggedInUser = currentUser
        }
    }

还有

struct ProfileView: View {
    @ObservedObject var sessionData: SessionData = SessionData.shared
    var body: some View {
      VStack{
        Text(self.sessionData.loggedInUser.first_name)
      }
    }
}

这样更改就会更新。但是如果我离开应用程序,我会丢失数据。

解决方案 2: 我也尝试像这样依赖从 UserDefault 读取数据

class SessionData : ObservableObject {
    func getLoggedInUser() -> User? {
        if let currentUser = UserDefaults.standard.object(forKey: "User") as? Data {
            let decoder = JSONDecoder()
            if let loadedUser = try? decoder.decode(User.self, from: currentUser) {
                return loadedUser
            }
        }
        return nil
    }
}

问题:一旦用户更改某些内容,我就无法获得更新:/

我没有找到同时使用 UserDefaults 和 ObservableObject 的好解决方案

【问题讨论】:

  • 您似乎没有任何代码可以从UserDefaults读取数据
  • 这是第二个问题。如果我依赖从 UserDefaults 读取数据,我将无法更新它们。
  • 为什么不能两者都做?您能否展示您尝试阅读但您认为阻止您更新数据的代码?
  • 我更新了描述
  • 听起来您基本上想要@AppStorage,但要与您使用 JSON 编码的自定义类型一起使用。您可以围绕 @AppStorage 创建一个新的属性包装器,或者您可以从头开始使用此处详述的主体:xavierlowmiller.github.io/blog/2020/09/04/iOS-13-AppStorage

标签: swift swiftui


【解决方案1】:

在“getLoggedInUser()”中,您没有更新已发布的 var“loggedInUser”。 每当您使用该功能时,请尝试执行此更新:

func getLoggedInUser() -> User? {
    if let currentUser = UserDefaults.standard.object(forKey: "User") as? Data {
        let decoder = JSONDecoder()
        if let loadedUser = try? decoder.decode(User.self, from: currentUser) {
            loggedInUser = loadedUser  // <--- here
            return loadedUser
        }
    }
    return nil
}

或者只是这样:

func getLoggedInUser2() {
    if let currentUser = UserDefaults.standard.object(forKey: "User") as? Data {
        let decoder = JSONDecoder()
        if let loadedUser = try? decoder.decode(User.self, from: currentUser) {
            loggedInUser = loadedUser  // <--- here
        }
    }
}

您也可以这样做以在用户更改时自动保存用户(而不是使用 setLoggedInUser):

@Published var loggedInUser: User = User(first_name: "", last_name: "", email: "") {
    didSet {
        if let encoded = try? JSONEncoder().encode(loggedInUser) {
            UserDefaults.standard.set(encoded, forKey: "User")
        }
    }
}

并将其用作 init(),这样您就可以在离开应用程序时取回保存的内容:

init() {
    getLoggedInUser2()
}

【讨论】: