如何持久化存储[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
相关产品推荐
相关产品推荐

