You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何持久化存储[String:[Restaurant]]类型字典避免应用重启丢失数据?

解决自定义类字典的持久化问题

老兄,要搞定重启App后数据不丢失的问题,核心是让你的Restaurant类支持序列化/反序列化,再把字典转成可存储的格式(比如Data),最后存到持久化容器里。我给你一步步拆解:

第一步:让Restaurant支持编码解码

自定义类默认没法直接被存储,所以得让它遵循Codable协议——这个协议是Swift专门用来处理对象和数据互相转换的,刚好适配我们的需求:

class Restaurant: Codable { // 新增Codable协议
    var name: String? 
    init?(name: String) { 
        guard !name.isEmpty else { return nil } 
        self.name = name 
    }
}

因为你的name属性是String?(本身就支持Codable),所以只要加个协议声明,Swift会自动帮我们生成编码解码的逻辑,不用额外写代码。

第二步:实现存储和读取方法

这里分两种场景推荐:

场景1:数据量不大(用UserDefaults)

UserDefaults是最简单的轻量持久化方案,适合存储小体量的数据:

// 把字典存到UserDefaults
func saveRestaurants() {
    do {
        // 将字典编码成Data格式
        let data = try JSONEncoder().encode(restaurants)
        UserDefaults.standard.set(data, forKey: "SavedRestaurants")
    } catch {
        print("存储失败:\(error.localizedDescription)")
    }
}

// 从UserDefaults读取字典
func loadRestaurants() -> [String: [Restaurant]]? {
    guard let data = UserDefaults.standard.data(forKey: "SavedRestaurants") else {
        return nil
    }
    do {
        // 将Data解码回原字典类型
        return try JSONDecoder().decode([String: [Restaurant]].self, from: data)
    } catch {
        print("读取失败:\(error.localizedDescription)")
        return nil
    }
}

场景2:数据量较大(用本地文件)

如果你的餐厅数据很多,UserDefaults就不太合适了,建议存在App的Documents目录下:

// 获取App的Documents目录路径
private func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}

// 存储到本地文件
func saveRestaurantsToFile() {
    let fileURL = getDocumentsDirectory().appendingPathComponent("restaurants.json")
    do {
        let data = try JSONEncoder().encode(restaurants)
        try data.write(to: fileURL)
    } catch {
        print("文件存储失败:\(error.localizedDescription)")
    }
}

// 从本地文件读取
func loadRestaurantsFromFile() -> [String: [Restaurant]]? {
    let fileURL = getDocumentsDirectory().appendingPathComponent("restaurants.json")
    guard let data = try? Data(contentsOf: fileURL) else {
        return nil
    }
    do {
        return try JSONDecoder().decode([String: [Restaurant]].self, from: data)
    } catch {
        print("文件读取失败:\(error.localizedDescription)")
        return nil
    }
}

第三步:在页面加载时初始化数据

不管用哪种存储方式,都要在viewDidLoad里先尝试读取已存数据,没有的话再初始化空字典:

var restaurants = [String: [Restaurant]]() 

override func viewDidLoad() { 
    super.viewDidLoad() 
    // 优先读取已存储的数据(这里以UserDefaults为例,换成文件方法同理)
    if let savedRestaurants = loadRestaurants() {
        restaurants = savedRestaurants
    }
    // 首次启动时初始化测试数据
    if restaurants.isEmpty {
        if let pizzaShop = Restaurant(name: "Mario's Pizza") {
            restaurants["Pizza"] = [pizzaShop]
            saveRestaurants() // 别忘了存起来!
        }
    }
}

关键提醒

每次修改restaurants字典后,一定要调用存储方法!比如添加、删除餐厅后:

// 示例:添加新餐厅
if let burgerJoint = Restaurant(name: "Burger King") {
    restaurants["Burgers", default: []].append(burgerJoint)
    saveRestaurants() // 立即持久化修改
}

内容的提问来源于stack exchange,提问作者Hekes Pekes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:14:24