After upgrading to iOS 18, my Core Data stack using NSPersistentCloudKitContainer in a shared App Group container stopped syncing correctly. The persistent store configuration, which previously worked in iOS 17, now experiences delayed or missing sync updates between devices. Then the app freezes and writes terminal the same error detail (which I provided) too many times.
The debug logs from the CloudKit mirroring delegate (NSCloudKitMirroringDelegate) show repetitive notifications but no updates in persistent history. Additionally, the persistent history tracking key appears unresponsive to local changes, causing transactions to fail in updating or syncing as expected.
Key setup details:
-
Core Data is set up within an App Group container using NSPersistentCloudKitContainer.
-
NSPersistentHistoryTrackingKey and NSPersistentStoreRemoteChangeNotificationPostOptionKey options are set to true.
Any insights into changes in iOS 18 Core Data or CloudKit handling with NSPersistentCloudKitContainer, especially around history tracking and sync delays, would be greatly appreciated. Thank you.
Error Detail
file:///private/var/mobile/Containers/Shared/AppGroup/BF95D309-EBE9-485E-B5CE-AA17097F7B60/[AppName]Database.sqlite
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:](3123): <NSCloudKitMirroringDelegate: 0x3032b4870>: Observed context save: <NSPersistentStoreCoordinator: 0x302694bd0> - <NSManagedObjectContext: 0x3036b1a00>
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate remoteStoreDidChange:](3166): <NSCloudKitMirroringDelegate: 0x3032b4870>: Observed remote store notification: <NSPersistentStoreCoordinator: 0x302694bd0> - 090C4244-0101-4DEF-90D6-1260570F47A5 - <NSPersistentHistoryToken - {
"090C4244-0101-4DEF-90D6-1260570F47A5" = 9;
}> -
Persistence.swift
struct PersistenceController {
let container: NSPersistentCloudKitContainer
static let shared = PersistenceController()
static var preview: PersistenceController = {PersistenceController()}()
init() {
container = NSPersistentCloudKitContainer(name: "[AppName]")
// Configure CloudKit for the default container
if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.[CompanyName].[AppName]") {
let storeURL = url.appendingPathComponent("[AppName]Database.sqlite")
let description = container.persistentStoreDescriptions.first
description?.url = storeURL
description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
container.persistentStoreDescriptions = [description].compactMap { $0 }
}
container.loadPersistentStores { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
}