Xcode报错:There is another instance of this persistent store actively syncing with CloudKit in this process.
Xcode报错:There is another instance of this persistent store actively syncing with CloudKit in this process.

Xcode报错:There is another instance of this persistent store actively syncing with CloudKit in this process.

在 SwiftUI 项目的ViewModel文件中获取上下文和数组对象,将数据插入到SwiftData。

private func createLifeSavingBank() throws {
    // 获取上下文
    let container: try? ModelContainer(for: PiggyBank.self)
    let context = container.mainContext
    
    // 创建新的人生存钱罐
    let piggyBank = PiggyBank()
    context.insert(piggyBank) // 将对象插入到上下文中
    
    // 保存上下文
    do {
        try context.save() // 提交上下文中的所有更改
    } catch {
        throw CalculationError.saveFailed(error)
    }
}

当 context.save() 调用,并保存到上下文时。UI界面并没有显示创建的存钱罐。

Xcode提示:

CloudKit setup failed because it couldn't register a handler for the export activity. There is another instance of this persistent store actively syncing with CloudKit in this process.

该问题表示,Core Data 在 CloudKit 模式下,每个 NSPersistentCloudKitContainer 会注册一个“导出活动 handler”(export handler),用于把本地改动同步到 CloudKit。

同一个持久化存储(store)已经有一个同步 handler 在运行,又尝试创建了另一个 container 或者上下文去操作同一个 store。

结果:Core Data 内部会报错,但通常它会“重置内部状态”,然后继续尝试同步。

提示:SwiftData 底层为 CoreData,因此这里会出现CoreData相关的内容。

需要等待一段时间,才会看到新创建的存钱罐。这是因为本地已经存在,但是CloudKit同步有问题。

问题原因

经过排查发现,问题的主要原因在于,app启动时已经创建了一次 ModelContainer。

@main
struct pigletApp: App {
    @State private var modelConfigManager = ModelConfigManager()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(try! ModelContainer(for: PiggyBank.self,SavingsRecord.self,configurations: modelConfigManager.currentConfiguration))
    }
}

在ViewModel文件中,每次调用createLifeSavingBank() 又会创建新的 ModelContainer(for: PiggyBank.self)。

这就导致重复创建ModelContainer,而触发报错。

解决方案

因为ModelContainer需要在View视图以及类中访问,可以创建一个全局单例管理器,只初始化一次ModelContainer:

import SwiftUI
import SwiftData

@MainActor
final class DataController {
    static let shared = DataController()
    let container: ModelContainer
    var context: ModelContext { container.mainContext }
    
    private init() {
        self.container = try! ModelContainer(
            for: PiggyBank.self,
                 SavingsRecord.self,
            configurations: ModelConfigManager.shared.currentConfiguration)
    }
}

在入口文件注入单例:

@main
struct pigletApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(DataController.shared.container) // 注入全局唯一 container
    }
}

在View视图中可以通过@Environment(\.modelContext) 获取:

struct ContentView: View {
    @Environment(\.modelContext) private var context  // 从 Environment 获取 context
    
    @Query(sort: \.creationDate, order: .forward)
    private var piggyBanks: [PiggyBank]
    ...
}

在ViewModel文件中,也可以直接使用ModelContainer单例:

private func createLifeSavingBank() throws {
    private let context = DataController.shared.context
    
    // 创建新的人生存钱罐
    let piggyBank = PiggyBank()
    context.insert(piggyBank) // 将对象插入到上下文中
    
    // 保存上下文
    do {
        try context.save() // 提交上下文中的所有更改
    } catch {
        throw CalculationError.saveFailed(error)
    }
}

通过全局单例,统一管理ModelContainer容器,这样可以保证 CloudKit handler 只注册一次,避免报错。

扩展内容

完整报错信息:

BUG IN CLIENT OF CLOUDKIT: Registering a handler for a CKScheduler activity identifier that has already been registered (com.apple.coredata.cloudkit.activity.export.1...F).
error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate resetAfterError:andKeepContainer:](605): <NSCloudKitMirroringDelegate: 0x3019182d0> - resetting internal state after error: Error Domain=NSCocoaErrorDomain Code=134422 "CloudKit setup failed because it couldn't register a handler for the export activity. There is another instance of this persistent store actively syncing with CloudKit in this process." UserInfo={NSUnderlyingException=Illegal attempt to register a second handler for activity identifier com.apple.coredata.cloudkit.activity.export.1...F, NSURL=file:///private/var/mobile/Containers/Shared/AppGroup/7F818A8E-12EE-446C-8862-12911100FE01/Library/Application%20Support/default.store, activityIdentifier=com.apple.coredata.cloudkit.activity.export.134832D0-817B-4347-8C74-D8C97EEB158F, NSLocalizedFailureReason=CloudKit setup failed because it couldn't register a handler for the export activity. There is another instance of this persistent store actively syncing with CloudKit in this process.}
error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate tearDown:]_block_invoke(808): <NSCloudKitMirroringDelegate: 0x3019182d0>: Told to tear down with reason: Error NSCocoaErrorDomain:134422
   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注