Core Data预览报错问题
Core Data预览报错问题

Core Data预览报错问题

问题描述

在SwiftUI中,当配置Core Data后,运行Core Data相关命令,例如增删操作时,就可能会报错。

例如,在SwiftUI的View视图中,配置了Core Data代码。当点击添加按钮时,调用addFetchedResult(context: viewContext)方法。

func addFetchedResult(context: NSManagedObjectContext) {
    let newEurofxrefhist = Eurofxrefhist(context: context)
    newEurofxrefhist.date = Date()
    newEurofxrefhist.currencySymbol = "USD"
    newEurofxrefhist.exchangeRate = 7

    do {
        try context.save()
    } catch {
        let nsError = error as NSError
        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
    }
}

Xcode就会提示预览报错。

使用iPhone真机运行,应用没有报错或闪退,因此可以推断问题出在#Preview预览代码。

修改预览代码

#Preview {
    ContentView()
}

预览代码中只有一个视图,可能是因为缺失了Core Data上下文环境导致的预览报错。

#Preview {
    // 创建 NSPersistentContainer
    let container = NSPersistentContainer(name: "ExchangeRateDataModel")

    // 存储在内存中,防止写入磁盘
    container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")

    // 加载持久化存储
    container.loadPersistentStores { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    }
    
   return ContentView()
        .environment(\.managedObjectContext,container.viewContext)
}

在#Preview预览代码中配置NSPersistentContainer,并将viewContext通过environment传递给ContentView视图后,Xcode预览发生了报错。

解决方案

当我预加载一些数据进行预览时,Xcode预览不再报错。

//  预加载一些数据进行预览
let context = container.viewContext
let sampleData = Eurofxrefhist(context: context)
sampleData.date = Date()
sampleData.currencySymbol = "USD"
sampleData.exchangeRate = 7.0

do {
    try context.save()
} catch {
    print("Error saving preview data: \(error.localizedDescription)")
}

总结

@FetchRequest 依赖于 NSManagedObjectContext 提供的持久化存储进行数据获取。如果数据库是空的,FetchRequest 会尝试查询数据,但返回一个空的 FetchedResults,并且在 #Preview 环境下,这种情况可能导致未预料的行为,比如:

exchangeRates.isEmpty 触发 UI 更新时没有数据,导致 UI 出现异常。

ForEach 在没有数据的情况下会尝试渲染空视图,预览时容易引发不可预料的错误。

Core Data 的持久化容器没有数据时,@FetchRequest 可能无法成功触发数据绑定。

Core Data预览报错的问题,最终在#Preview中配置Core Data上下文环境以及新增示例数据的情况下,得到解决。

后续涉及Core Data预览时,应该考虑添加示例数据,防止 FetchRequest 返回空值。

如果有多个实体或复杂数据,可以使用 PersistenceController.preview 进行统一管理。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注