SwiftUI如何实现用户自定义数组持久化存储,应用重启后数据仍保留?
收藏列表持久化实现方案
@AppStorage 不支持直接存储自定义类型数组,轻量场景下可以通过「Codable 序列化 + UserDefaults 存储」的方案实现数据持久化,无需引入复杂的数据库方案,实现步骤如下:
步骤1:给自定义类型添加 Codable 协议
首先确保你的 Categories 结构体遵守 Codable 协议,用于数组的序列化和反序列化,你已经用到了 firstIndex、contains 方法说明已经遵守了 Equatable,直接加协议即可:
struct Categories: Identifiable, Equatable, Codable { // 原有属性保持不变即可,String、Int等基础类型默认支持Codable }
步骤2:给 ViewModel 添加持久化逻辑
修改你的 CategoriesModel,新增本地读写逻辑,初始化时自动读取已存储的收藏数据:
class CategoriesModel: ObservableObject { // 存储用的固定Key,避免写错 private let saveKey = "savedRestaurantList" // 可以通过didSet实现修改自动存,无需手动调用保存方法 @Published var savedList: [Categories] = [] { didSet { saveToLocal() } } init() { // 初始化时从本地读取已保存的收藏列表 loadFromLocal() } // 从本地读取收藏列表 private func loadFromLocal() { guard let data = UserDefaults.standard.data(forKey: saveKey) else { // 本地没有存储过数据,返回空数组 savedList = [] return } do { savedList = try JSONDecoder().decode([Categories].self, from: data) } catch { print("收藏列表读取失败: \(error.localizedDescription)") savedList = [] } } // 把当前收藏列表保存到本地 private func saveToLocal() { do { let data = try JSONEncoder().encode(savedList) UserDefaults.standard.set(data, forKey: saveKey) } catch { print("收藏列表保存失败: \(error.localizedDescription)") } } }
步骤3:优化原有业务代码(可选,但建议修改)
你原有代码里的强制解包、单独维护的isSaved状态都有潜在风险,可以优化如下:
struct DetailView2: View { var restaurantInfo: Categories @EnvironmentObject var a: CategoriesModel // 不需要单独维护isSaved状态,直接判断数组是否包含当前餐厅即可,避免状态不同步 var body: some View { VStack { ZStack(alignment: .bottomLeading) { Image(restaurantInfo.pic) .resizable() .scaledToFit() Button(action: { if let index = a.savedList.firstIndex(of: restaurantInfo) { // 已收藏,执行取消 a.savedList.remove(at: index) } else { // 未收藏,执行添加 a.savedList.append(restaurantInfo) } // 因为ViewModel里加了didSet自动保存,这里不需要额外调用保存方法 }, label: { Image(systemName: a.savedList.contains(restaurantInfo) ? "bookmark.fill" : "bookmark") .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(12) .padding() }) } // 其余原有代码保持不变 } } }
补充说明
如果你的收藏数据量超过千条、或者需要做更复杂的查询筛选,可以改用 SwiftData 或 CoreData 实现,对于常规收藏需求,上述方案性能足够、实现成本最低。
内容的提问来源于stack exchange,提问作者sadel
相关产品推荐
相关产品推荐

