SwiftUI 中的@AppStorage 和 UserDefaults


UserDefaults 一般用于小数据的持久性存储,当 App 启动时,系统会自动加载 UserDefaults 中的数据,如果存太多数据到 UserDefaults 中,那么 App 的启动有可能会变慢。最多不要超过512KB 的数据

UserDefaults 的使用很简单,一个是取,一个是存,但是 UserDefaults 不会马上存储值,iOS 系统认为用户可能会来来回回多次切换启动,所以 iOS 会在某些时刻将这些改变一次性写入保存。如果需要马上存储值需要手动调用同步。

UserDefaults 写入用 set() 方法,可以指定写入的数据类型,也可以不指定,Swift 推断

UserDefaults.standard.set(number, forKey: "number")

UserDefaults 读取用 KVC 的键值读取,可以指定数据类型读取

UserDefaults.standard.integer(forKey: "number")

常规我们使用 UserDefaults 一般是这么配套使用

struct ContentView: View {
@State private var number = UserDefaults.standard.integer(forKey: "number")
var body: some View {
Text("(number)")
Button("增加"){
number += 1
UserDefaults.standard.set(number, forKey: "number")
UserDefaults.standard.synchronize()
}
}
}

但是这种传统的使用方式,没有默认值,比如 读取 Boolean 值,当通过 UserDefaults 读取的 key 不存在时会返回 false ,但是这个 false 是真的我们真正业务逻辑上的 false 吗?

在 SwiftUI 中 ,提供了更为简单的用法,SwiftUI 提供了一个 @AppStorage 的属性包装器,可以简化对 UserDefaults 的使用

struct ContentView: View {
@AppStorage("number") var number = 0
var body: some View {
Text("(number)")
Button("增加"){
number += 1
}
}
}

UserDefaults 通过 @AppStorage 属性包装器访问,这个包装器也有 @State一样的功能, 当值发生改变时,它会根据新值重新更新 UI。括号中的字符串其实就是 UserDefaults 存储的 key ,它不必和属性取名相同,可以是任何字符串。

通过 @AppStorage 属性包装器使用 UserDefaults 还可以提供默认值,杜绝传统用法中的情况。

@AppStorage 不能处理复杂数据类型的存储(如 自定义的Swift 结构体),这可能就是 UserDefaults 不建议存储太多数据的一个提醒。如果要存储复杂数据类型,还是要直接使用 UserDefaults

UserDefaults存储自定义类型数据

UserDefaults 存储自定义类型数据需要遵循 Codable 协议,如果自定义类型中的属性都遵循 Codable 协议,那么自定义类型只需要遵循协议即可,系统会自动处理归档和解归档的相关代码。

将自定义类型数据存储在 UserDefaults 中需要使用 JSONEncoder  将其转成 Data 类型。

从 UserDefaults 取出自定义类型数据 则需要将 Data 使用 JSONDecoder 转成自定义类型。

如存储自定义类型数据

struct User: Codable {
var name: String
var age: String
}

保存自定义类型数据

struct ContentView: View {
@State private var user = User(name: "CK", age: "18")
var body: some View {
Text("(user.name) --- (user.age)")
Button("保存"){
let jsonEncoder = JSONEncoder()
if let data = try? jsonEncoder.encode(user) {
UserDefaults.standard.set(data, forKey: "user")
UserDefaults.standard.synchronize()
}
}
}
}

取出自定义类型数据

struct ContentView: View {
@State private var user = User(name: "CK", age: "18")
@State private var currentUser: User?
var body: some View {
Text("(user.name) --- (user.age)")
Button("保存"){
let jsonEncoder = JSONEncoder()
if let data = try? jsonEncoder.encode(user) {
UserDefaults.standard.set(data, forKey: "user")
UserDefaults.standard.synchronize()
}
}
Button("取出") {
let jsonDecoder = JSONDecoder()
let data = UserDefaults.standard.data(forKey: "user")
guard let data = data else { return }
if let user = try? jsonDecoder.decode(User.self, from: data) {
currentUser = user
}
}
if let user = currentUser {
Text("显示取出的数据: (user.name) --- (user.age)")
}
}
}


原文始发于微信公众号(三万之一):SwiftUI 中的@AppStorage 和 UserDefaults

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/231275.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!