我遇到了一个问题,在更新应用程序后,Core Data 迁移过程对少数用户卡住了。
我正在使用 SwiftUI + Core Data,目标是 iOS 15.0+。
我不确定原因,无法在本地重现。
对模型的相应修改是为两个实体添加一个非可选的Int64字段,其他没有变化。用户的崩溃日志对应于
container.loadPersistentStores(completionHandler: { (storeDescription, error) in,
行所以我假设错误发生在迁移过程中。
我曾多次尝试在本地环境中重现崩溃,但都失败了。我的环境中的迁移过程对我来说似乎很好。
已排除的可能性有:
我已经为新的非可选 Int64 设置了默认值,这里是模型更改的相关 git diff。加粗的“订单”字段是我添加的新字段。
<entity name="Preset" representedClassName="Preset" syncable="YES">
<attribute name="createTime" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="detail" optional="YES" attributeType="String"/>
**<attribute name="order" attributeType="Integer 64" minValueString="0" defaultValueString="0" usesScalarValueType="YES"/>**
<relationship name="belongsTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Project" inverseName="presets" inverseEntity="Project"/>
<relationship name="tagBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Tag" inverseName="presets" inverseEntity="Tag"/>
</entity>
...
<attribute name="id_" optional="YES" attributeType="String"/>
<attribute name="isArchived" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="name" optional="YES" attributeType="String"/>
**<attribute name="order" attributeType="Integer 64" minValueString="0" defaultValueString="0" usesScalarValueType="YES"/>**
<relationship name="entries" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="TimeEntry" inverseName="belongsTo" inverseEntity="TimeEntry"/>
<relationship name="presets" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Preset" inverseName="belongsTo" inverseEntity="Preset"/>
...
这里是我的 Persistence.swift 容器初始化代码:
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "Project")
guard let groupContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.Project") else {
logger.critical("Persistant init failed to get groupContainerURL")
preconditionFailure("Persistant init failed to get groupContainerURL")
}
let storeURL = groupContainerURL.appendingPathComponent("Project.sqlite")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
} else {
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
}
if container.isNeedMigration(url: storeURL) {
logger.notice("Core Data model need Migration")
#if APP_WIDGET
for idx in 0..<3 {
logger.notice("Widget sleeping \(idx+1).")
sleep(3)
if !container.isNeedMigration(url: storeURL) {
break
}
}
#endif
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
logger.critical("Unresolved error \(error.localizedDescription, privacy: .public), \(error.userInfo, privacy: .public), error: \(error)")
fatalError("Unresolved error \(error.localizedDescription), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
所以我想找出崩溃的原因并修复它,请给我一些建议,谢谢。