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

Core Data三表中两表修改未保存,疑与迁移操作相关

Core Data重启后部分数据丢失问题求助

使用Core Data存储数据,通过DB Browser for SQLite查看模拟器数据库。执行数据创建流程后,数据库中所有条目和关联正常显示,但重启应用后,FoodItem条目保留,ComposedFoodItem、Ingredient条目及关联关系全部消失。

核心数据创建函数

/**
 Creates a new ComposedFoodItem from the ComposedFoodItemViewModel.
 Creates the related FoodItem and the Ingredients.
 Creates all relationships.
 
 - Parameter composedFoodItemVM: The source view model.
 
 - Returns: A Core Data ComposedFoodItem; nil if there are no Ingredients.
 */
static func create(from composedFoodItemVM: ComposedFoodItemViewModel, generateTypicalAmounts: Bool) -> ComposedFoodItem? {
    debugPrint(AppDelegate.persistentContainer.persistentStoreDescriptions) // The location of the .sqlite file
    let moc = AppDelegate.viewContext
    
    // Create new ComposedFoodItem (1)
    let cdComposedFoodItem = ComposedFoodItem(context: moc)
    
    // No existing composed food item, therefore create a new UUID
    cdComposedFoodItem.id = UUID()
    
    // Fill data
    cdComposedFoodItem.amount = Int64(composedFoodItemVM.amount)
    cdComposedFoodItem.numberOfPortions = Int16(composedFoodItemVM.numberOfPortions)
    
    // Create the related FoodItem (2)
    let cdFoodItem = FoodItem.create(from: composedFoodItemVM, generateTypicalAmounts: generateTypicalAmounts)
    
    // Relate both (3)
    cdComposedFoodItem.foodItem = cdFoodItem
    
    // Add cdComposedFoodItem to composedFoodItemVM
    composedFoodItemVM.cdComposedFoodItem = cdComposedFoodItem
    
    // Save before adding Ingredients, otherwise this could lead to an NSInvalidArgumentException (4)
    try? moc.save()
    
    // Add new ingredients (5)
    if let cdIngredients = Ingredient.create(from: composedFoodItemVM) {
        cdComposedFoodItem.addToIngredients(NSSet(array: cdIngredients))
        
        // Save new composed food item
        try? moc.save()
        
        // Return the ComposedFoodItem
        return cdComposedFoodItem
    } else {
        // There are no ingredients, therefore we delete it again and return nil
        moc.delete(cdComposedFoodItem)
        try? moc.save()
        return nil
    }
}

执行流程

    1. 在ComposedFoodItem表创建新条目
    1. 在FoodItem表创建新条目
    1. 建立两个条目关联
    1. 保存修改(此时数据库可见两个新条目及正确关联)
    1. 在Ingredient表创建1~n个新条目并关联到步骤1的条目

自定义迁移策略背景

近期完成了从数据模型版本1("EasyFPU")到版本2("EasyFPU 2")的Core Data迁移,针对ComposedFoodItem和Ingredient表设置了自定义迁移策略,逻辑一致:

/**
 No Ingredient is created in the destination model, i.e., there will be no Ingredients
 */
override func createDestinationInstances(forSource sourceIngredient: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
    // Do nothing on purpose
    debugPrint("Not migrating Ingredient with ID: \((sourceIngredient as? Ingredient)?.id.uuidString ?? "unknown")")
}

怀疑迁移策略在重启时被触发,但断点未捕获到debugPrint输出,迁移本应已完成。

AppDelegate中Core Data容器配置

lazy var persistentContainer: NSPersistentCloudKitContainer = {
    let container = NSPersistentCloudKitContainer(name: "EasyFPU")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

曾尝试修改容器名从"EasyFPU"到"EasyFPU 2",但确认容器名称与模型版本无关。

请问有哪些可能的解决思路?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:45:05