核心数据替换持久存储错误“无法替换目标数据库”

问题描述 投票:0回答:1

我在应用程序中进行了手动逐步迁移,除了一些极少数情况下

replacePersistentStore(at destinationURL: URL...)
失败并出现错误:“Error Domain=NSSQLiteErrorDomain Code=5”(null)" UserInfo={NSFilePath=/private/ 时,它工作正常。 var/mobile/Containers/Shared/AppGroup/430DC264-B4D6-4853-A298-E989A5AC7E5E/MyApp/MyAppStorage.sqlite,源数据库路径=/private/var/mobile/Containers/Data/Application/73B79AA0-F609-4ABA-A864 -D9FFBC829393/tmp/E29D6F57-3BFB-46BD-A2AD-999907876BC6/MyAppStorage.sqlite,原因=无法替换目标数据库”。

我调查了这个问题并尝试重现它但无法重现。我仅在 Firebase Crashlytics 上看到这些崩溃。为了防止这个问题 - 在迁移完成之前我不会加载存储。 也许其他人也遇到过同样的问题或知道原因。 这是我的代码:

extension NSPersistentStoreCoordinator {
static func replaceStore(
    at targetURL: URL,
    withStoreAt sourceURL: URL,
    options: [String: Any]
) {
    do {
        let persistentStoreCoordinator = NSPersistentStoreCoordinator(
            managedObjectModel: NSManagedObjectModel()
        )
        try persistentStoreCoordinator.replacePersistentStore(
            at: targetURL,
            destinationOptions: options,
            withPersistentStoreFrom: sourceURL,
            sourceOptions: options,
            ofType: NSSQLiteStoreType
        )
    } catch let error {
        fatalError("failed to replace persistent store at \(targetURL) with \(sourceURL), error: \(error)")
    }
}

...

func createTmpMigrationDirectory(url: URL) {
    do {
        try FileManager.default.createDirectory(
            at: url,
            withIntermediateDirectories: true,
            attributes: nil
        )
    } catch {
        Logger.logError("Failed to create directory at path: \(url), error: \(error)")
        fatalError("failed to create directory at path: \(url), error: \(error)")
    }
}

func removeTmpMigrationDirectory(url: URL) {
    do {
        try FileManager.default.removeItem(at: url)
    } catch {
        Logger.logError("Failed to remove item at path: \(url), error: \(error)")
    }
}

...

func migration(
    with step: CoreDataMigrationStep,
    sourceURL: URL,
    options: [String: Any]
) {
    autoreleasepool {
        let manager = NSMigrationManager(
            sourceModel: step.source,
            destinationModel: step.destination
        )
        let directoryURL = URL(
            fileURLWithPath: NSTemporaryDirectory()
        ).appendingPathComponent(UUID().uuidString)
        
        createTmpMigrationDirectory(url: directoryURL)
        
        let destinationURL = directoryURL.appendingPathComponent(
            sourceURL.lastPathComponent
        )
        
        do {
            try manager.migrateStore(
                from: sourceURL,
                sourceType: NSSQLiteStoreType,
                options: options,
                with: step.mapping,
                toDestinationURL: destinationURL,
                destinationType: NSSQLiteStoreType,
                destinationOptions: options
            )
        } catch {
            fatalError("failed attempting to migrate from \(step.source) to \(step.destination), error: \(error)")
        }
        
        NSPersistentStoreCoordinator.replaceStore(
            at: sourceURL,
            withStoreAt: destinationURL,
            options: options
        )
        
        removeTmpMigrationDirectory(url: directoryURL)
    }
}
swift core-data core-data-migration
1个回答
1
投票

该代码没有任何明显的错误。

错误消息提到 SQLite 错误代码 5,这意味着 Core Data 出现 SQLITE_BUSY 错误。这表明替换调用失败,因为您正在尝试替换某处正在使用的持久存储。这可能在您的应用程序中,或者如果您有应用程序扩展,它可能位于其中之一中。

要追踪此情况,您需要找出发生情况的位置。在您的应用程序中,您需要确保您没有使用任何可以连接到您要替换的持久存储的东西。如果它是一个扩展,您需要以某种方式与其协调,以确保它不会妨碍。

© www.soinside.com 2019 - 2024. All rights reserved.