Swift:如何在@Observable类中使用@AppStorage?
在SwiftUI新@Observable系统中替代@AppStorage的方案
目前Xcode 15 Beta 2中,@AppStorage无法直接在@Observable类中使用,因为该属性包装器依赖SwiftUI环境中的UserDefaults上下文,而@Observable类默认不具备这个环境。以下是几种可行的替代方案:
方案1:手动封装UserDefaults(基础版)
利用@Observable自动追踪属性变化的特性,手动实现属性与UserDefaults的同步:
import SwiftUI @Observable class UserInfo { var username: String { didSet { UserDefaults.standard.set(username, forKey: "username") } } init() { // 初始化时从UserDefaults读取值,无值则用默认空字符串 self.username = UserDefaults.standard.string(forKey: "username") ?? "" } }
- 当
username属性修改时,didSet会自动将新值写入UserDefaults @Observable会自动触发视图刷新,无需额外手动发布通知
方案2:依赖注入UserDefaults(进阶版)
如果需要支持自定义UserDefaults实例(比如测试场景),可以将其作为依赖注入,提升灵活性:
import SwiftUI @Observable class UserInfo { private let defaults: UserDefaults var username: String { didSet { defaults.set(username, forKey: "username") } } // 默认使用标准UserDefaults,也可传入自定义实例 init(defaults: UserDefaults = .standard) { self.defaults = defaults self.username = defaults.string(forKey: "username") ?? "" } }
- 适合单元测试:可以传入内存中的
UserDefaults实例,避免污染真实存储 - 多场景适配:比如共享App Group的
UserDefaults
方案3:视图层使用@AppStorage同步到Observable类
如果偏好保留@AppStorage的使用,可以在视图层维护存储,再同步到@Observable类:
struct ContentView: View { @AppStorage("username") private var storedUsername: String = "" @State private var userInfo = UserInfo() var body: some View { TextField("输入用户名", text: $storedUsername) // 存储值变化时同步到UserInfo .onChange(of: storedUsername) { newValue in userInfo.username = newValue } // 视图出现时初始化UserInfo的值 .onAppear { userInfo.username = storedUsername } } } @Observable class UserInfo { var username: String = "" }
- 适合简单场景,但需要手动维护视图与类之间的同步,不如前两种方案优雅
注:后续Xcode正式版或更新的Beta版本可能会支持
@AppStorage直接在@Observable类中使用,当前版本可采用上述方案替代。
内容的提问来源于stack exchange,提问作者scotland1912
相关产品推荐
相关产品推荐

