You need to enable JavaScript to run this app. SwiftUI中结合UserDefaults与ObservableObject的最佳使用方式
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中结合UserDefaults与ObservableObject的最佳使用方式

适配UserDefaults与ObservableObject的实现方案

问题根源有两点:

  1. 第一个实现方案没有在类初始化时加载UserDefaults中已存储的缓存数据,且set方法存在变量名错误,导致应用重启后数据丢失
  2. 第二个实现方案没有用@Published修饰用户数据属性,数据修改后无法触发视图更新通知

下面是可直接使用的完整实现,同时满足实时更新视图、自动同步UserDefaults的需求:

import SwiftUI

// 首先确保你的User模型符合Codable协议
struct User: Codable {
    var first_name: String
    var last_name: String
    var email: String
}

class SessionData : ObservableObject {
    // @Published修饰保证修改时通知视图刷新
    @Published var loggedInUser: User {
        didSet {
            do {
                let encodedData = try JSONEncoder().encode(loggedInUser)
                UserDefaults.standard.set(encodedData, forKey: "User")
            } catch {
                print("存储用户数据失败: \(error)")
            }
        }
    }
    static let shared = SessionData()

    private init() {
        // 初始化时优先读取UserDefaults中已存储的用户数据
        if let savedUserData = UserDefaults.standard.data(forKey: "User") {
            do {
                loggedInUser = try JSONDecoder().decode(User.self, from: savedUserData)
                return
            } catch {
                print("解析用户数据失败: \(error)")
            }
        }
        // 没有缓存数据时使用默认空值
        loggedInUser = User(first_name: "", last_name: "", email: "")
    }
}

如果你习惯用Combine框架实现,也可以替换成对应写法,逻辑完全一致:

import SwiftUI
import Combine

class SessionData : ObservableObject {
    @Published var loggedInUser: User
    static let shared = SessionData()
    private var userUpdateObserver: AnyCancellable?

    private init() {
        // 初始化读取缓存逻辑和上面一致
        if let savedUserData = UserDefaults.standard.data(forKey: "User") {
            do {
                loggedInUser = try JSONDecoder().decode(User.self, from: savedUserData)
            } catch {
                print("解析用户数据失败: \(error)")
                loggedInUser = User(first_name: "", last_name: "", email: "")
            }
        } else {
            loggedInUser = User(first_name: "", last_name: "", email: "")
        }
        
        // 监听属性变化自动同步到UserDefaults
        userUpdateObserver = $loggedInUser
            .sink(receiveValue: { newUser in
                do {
                    let encodedData = try JSONEncoder().encode(newUser)
                    UserDefaults.standard.set(encodedData, forKey: "User")
                } catch {
                    print("存储用户数据失败: \(error)")
                }
            })
    }
}

视图调用方式

原有视图代码无需修改,直接修改属性就会自动同步存储并刷新界面:

struct ProfileView: View {
    @ObservedObject var sessionData: SessionData = SessionData.shared
    var body: some View {
      VStack{
        Text(sessionData.loggedInUser.first_name)
        // 测试修改按钮
        Button("修改用户名") {
            sessionData.loggedInUser.first_name = "新用户名"
        }
      }
    }
}

内容的提问来源于stack exchange,提问作者A Akrm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 18:54:02