SwiftData数据无法持久化:宏追踪应用编辑后数据不保存
SwiftData修改无法持久化问题
我正在开发一款宏追踪应用,但使用SwiftData时,编辑数据后从未成功保存。每次关闭应用后,所有对象都会恢复到初始状态,数据并未删除但修改无法持久化。打印变量显示数据已正常编辑,手动保存也没用,看过的待办应用教程帮助不大。
相关代码
应用入口代码
@main struct Macro_TrackerApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Macros.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { TabBarView() } .modelContainer(sharedModelContainer) } }
数据模型代码
@Model class Macros: Identifiable { @Attribute(.unique) var id: String = UUID().uuidString var date: Date var fat: CGFloat var carbs: CGFloat var proteins: CGFloat var calories: CGFloat init(id: String = UUID().uuidString, date: Date, fat: CGFloat, carbs: CGFloat, proteins: CGFloat, calories: CGFloat = 0) { self.id = id self.date = date self.fat = fat self.carbs = carbs self.proteins = proteins self.calories = calories } }
更新数据方法
func updateMacros(dailyMacros: Macros) { dailyMacros.fat += quickAddFat dailyMacros.carbs += quickAddCarbs dailyMacros.proteins += quickAddProteins dailyMacros.calories += ((quickAddFat * 9) + (quickAddCarbs * 4) + (quickAddProteins * 4)) }
视图中的数据引用
@Environment(\.modelContext) private var modelContext @Query var macros: [Macros] var dailyMacros: Macros? { macros.first(where: { Calendar.current.isDate($0.date, equalTo: Date.now, toGranularity: .day) }) ?? nil }
触发更新的按钮代码
HStack { CustomButtonView(action: { viewModel.updateMacros(dailyMacros: dailyMacros) print(dailyMacros.carbs) print(macros.first(where: { Calendar.current.isDate($0.date, equalTo: Date.now, toGranularity: .day) })?.carbs) }, label: "Appliquer", color: Color.macroTrackerButton, width: 200, height: 50) }
初始化数据方法
func insert() { modelContext.insert(Macros(date: Date.now, fat: 0, carbs: 0, proteins: 0)) }
问题排查与解决
1. 强制手动保存上下文
SwiftData默认自动保存,但快速修改后立即退出可能来不及触发。在更新逻辑后添加手动保存:
func updateMacros(dailyMacros: Macros, modelContext: ModelContext) { dailyMacros.fat += quickAddFat dailyMacros.carbs += quickAddCarbs dailyMacros.proteins += quickAddProteins dailyMacros.calories += ((quickAddFat * 9) + (quickAddCarbs * 4) + (quickAddProteins * 4)) // 手动保存上下文 do { try modelContext.save() } catch { print("保存失败:\(error)") } }
注意要让ViewModel能拿到modelContext,可以在初始化ViewModel时从视图传入。
2. 修复日期匹配的精度问题
当前通过天级粒度匹配日期,但存储的Date包含时分秒,重启后可能因精度问题找不到原有数据,导致重新创建初始对象。给date属性添加转换器,只保留天级精度:
@Model class Macros: Identifiable { // ...其他属性 @Attribute(.transformable(transformer: DateDayTransformer.self)) var date: Date // ...初始化方法 } // 自定义日期转换器,只保留当天起始时间 class DateDayTransformer: ValueTransformer { override class func transformedValueClass() -> AnyClass { Date.self } override class func allowsReverseTransformation() -> Bool { true } override func transformedValue(_ value: Any?) -> Any? { guard let date = value as? Date else { return nil } return Calendar.current.startOfDay(for: date) } override func reverseTransformedValue(_ value: Any?) -> Any? { transformedValue(value) } }
3. 明确指定数据存储路径
给ModelConfiguration指定具体的存储URL,确保数据写入正确位置:
let modelConfiguration = ModelConfiguration( schema: schema, url: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appending(path: "MacroTracker.sqlite") )
4. 验证数据存储状态
通过Xcode的Window > Devices and Simulators选中应用,点击Download Container查看沙盒内的MacroTracker.sqlite文件,确认修改后文件时间是否更新,验证数据是否真的写入。
内容的提问来源于stack exchange,提问作者Killianoni
相关产品推荐
相关产品推荐

