MST

星途 面试题库

面试题:SwiftUI结合UserDefaults处理复杂数据结构的持久化

在SwiftUI应用里,有一个自定义结构体 `Person: Codable`,包含 `name`(字符串类型),`age`(整数类型)和 `hobbies`(字符串数组类型)。要求将多个 `Person` 实例存储到 `UserDefaults` 中,并能在需要时正确读取并显示在SwiftUI视图上,详细说明实现思路并给出代码。
39.6万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 由于 UserDefaults 只能存储特定类型的数据,Person 结构体虽然遵循 Codable 协议,但不能直接存储。需要先将 Person 实例编码为 Data 类型,再存储到 UserDefaults 中。
  2. 编码使用 JSONEncoder,解码使用 JSONDecoder
  3. 读取数据时,从 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()
        }
    }
}