实现思路
- 由于
UserDefaults
只能存储特定类型的数据,Person
结构体虽然遵循 Codable
协议,但不能直接存储。需要先将 Person
实例编码为 Data
类型,再存储到 UserDefaults
中。
- 编码使用
JSONEncoder
,解码使用 JSONDecoder
。
- 读取数据时,从
UserDefaults
中取出 Data
,再解码为 Person
实例数组,用于在 SwiftUI 视图上显示。
代码实现
import SwiftUI
// 自定义Person结构体
struct Person: Codable {
var name: String
var age: Int
var hobbies: [String]
}
// 存储Person实例到UserDefaults
func savePersonsToUserDefaults(persons: [Person]) {
do {
let encoder = JSONEncoder()
let data = try encoder.encode(persons)
UserDefaults.standard.set(data, forKey: "Persons")
} catch {
print("编码错误: \(error)")
}
}
// 从UserDefaults读取Person实例
func loadPersonsFromUserDefaults() -> [Person] {
guard let data = UserDefaults.standard.data(forKey: "Persons") else {
return []
}
do {
let decoder = JSONDecoder()
return try decoder.decode([Person].self, from: data)
} catch {
print("解码错误: \(error)")
return []
}
}
struct ContentView: View {
@State private var persons: [Person] = []
@State private var newName = ""
@State private var newAge = 0
@State private var newHobbies = ""
var body: some View {
VStack {
// 输入新Person信息
TextField("姓名", text: $newName)
Stepper("年龄: \(newAge)", value: $newAge, in: 0...100)
TextField("爱好(逗号分隔)", text: $newHobbies)
Button("添加") {
let hobbyArray = newHobbies.components(separatedBy: ",").map { $0.trimmingCharacters(in:.whitespaces) }
let newPerson = Person(name: newName, age: newAge, hobbies: hobbyArray)
persons.append(newPerson)
savePersonsToUserDefaults(persons: persons)
newName = ""
newAge = 0
newHobbies = ""
}
// 显示Person列表
List(persons) { person in
VStack(alignment:.leading) {
Text("姓名: \(person.name)")
Text("年龄: \(person.age)")
Text("爱好: \(person.hobbies.joined(separator: ", "))")
}
}
}
.onAppear {
persons = loadPersonsFromUserDefaults()
}
}
}