因为一个我以前从未遇到过的问题,我有点迷失,但是,我有一个怀疑。我使用 Core Data 进行数据存储,使用 DB Browser for SQLite 检查模拟器中运行的数据库。
这是所有核心数据处理发生的相关函数:
/**
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
}
}
该功能的作用:
所有这些工作正常,我可以看到数据库中的所有关系和条目。
然后我退出并重新启动应用程序。第 2 步中创建的条目仍然存在,但第 1 步和第 5 步中创建的条目以及关系(当然)都消失了。
我的怀疑:我最近实现了从数据模型版本 1(“EasyFPU”)到版本 2(“EasyFPU 2”)的核心数据迁移。在此迁移中,我有两个针对这两个表的自定义迁移策略,这两个表未存储。迁移策略非常简单(两个表相同):
/**
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 行中设置断点,实际上我永远不会像预期的那样到达该断点。然而,重新启动后,Ingredient 和 CompositFoodItem 这两个表是空的。
我的 AppDelegate Core Data permanentContainer 变量如下所示:
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”,但这显然不是版本,而是容器名称。
有什么想法吗?预先感谢!
问题已解决 - 这是一些测试的愚蠢遗留问题 - 这些表在应用程序启动时被主动删除。