Core Data迁移异常:loadPersistentStores()调用时应用崩溃排查
Core Data迁移崩溃问题解决方案
问题背景
调用loadPersistentStores()时触发Thread 1: EXC_BAD_ACCESS (code=1, address=0x1)崩溃,首次安装应用功能正常,可定位为Core Data迁移流程异常。
核心排查方向与修复方案
1. 修正自定义迁移策略的方法签名
自定义迁移策略的方法需与映射模型中的调用完全兼容Objective-C签名,原方法的参数标签在Objective-C中会被自动转换,导致方法找不到引发崩溃。
修改迁移策略代码:
class DaysMigrationPolicy : NSEntityMigrationPolicy { @objc func identificatorForId(_ id: Int16) -> UUID { return UUID() } @objc func isDisplayedWithId(_ id: Int16) -> Bool { return true } }
同时在迁移模型的属性映射中,确保调用的方法名与上述一致,例如:
- 目标属性
identificator的表达式写为FUNCTION($entityPolicy, "identificatorForId:", $source.id) - 目标属性
isDisplayed的表达式写为FUNCTION($entityPolicy, "isDisplayedWithId:", $source.id)
2. 验证迁移模型的配置准确性
- 打开迁移模型文件,检查实体迁移项的Custom Policy字段,需完整填写包含模块名的类路径(例如
你的AppTarget名称.DaysMigrationPolicy),确保系统能正确找到自定义迁移策略类。 - 核对源实体、目标实体的属性映射关系,确认源属性引用、方法调用无拼写错误。
3. 启用Core Data迁移调试日志
在Xcode的Run Scheme配置中,添加-com.apple.CoreData.MigrationDebug 1到Arguments Passed On Launch,控制台会输出迁移过程的详细日志,帮助定位具体是哪一步实体/属性处理时出现异常。
4. 检查持久化存储路径权限
打印storeURL的值,确认路径指向的App Group目录已正确配置,应用具备读写权限。若路径错误或无权限,会导致迁移过程中出现内存访问异常。
5. 尝试手动迁移(可选)
若自动迁移仍无法解决,可通过手动迁移代码控制流程,更精准捕获错误:
// 获取源模型、目标模型 guard let sourceModel = NSManagedObjectModel(contentsOf: Bundle.main.url(forResource: "旧模型名称", withExtension: "momd")!) else { fatalError("无法加载源模型") } guard let destinationModel = NSManagedObjectModel(contentsOf: Bundle.main.url(forResource: "Timetable_3_0 v2", withExtension: "momd")!) else { fatalError("无法加载目标模型") } // 迁移路径配置 let sourceStoreURL = URL.storeURL(for: "group.com.kondiko.Timetable", databaseName: "timetable") let tempDestinationURL = FileManager.default.temporaryDirectory.appendingPathComponent("migrated_timetable.sqlite") // 执行迁移 let mappingModel = NSMappingModel(from: [Bundle.main], forSourceModel: sourceModel, destinationModel: destinationModel) let migrationManager = NSMigrationManager(sourceModel: sourceModel, destinationModel: destinationModel) do { try migrationManager.migrateStore(from: sourceStoreURL, type: NSSQLiteStoreType, options: nil, with: mappingModel, toDestinationURL: tempDestinationURL, destinationType: NSSQLiteStoreType, destinationOptions: nil) // 迁移成功后替换原存储 try FileManager.default.removeItem(at: sourceStoreURL) try FileManager.default.moveItem(at: tempDestinationURL, to: sourceStoreURL) } catch { print("迁移失败:\(error)") }
内容的提问来源于stack exchange,提问作者kondiko21
相关产品推荐
相关产品推荐

