Created
April 12, 2026 21:46
-
-
Save Mcrich23/fb3e6c53cac8f256ff5adbf550038717 to your computer and use it in GitHub Desktop.
My best attempt to track when SwiftData/CoreData is syncing with CloudKit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| import CoreData | |
| /// A modifier that leverages several notifications to tell a bound variable if CoreData is syncing with CloudKit. | |
| private struct CoreDataIsSyncingModifier: ViewModifier { | |
| /// Tracks if `NSPersistentCloudKitContainer.eventChangedNotification` has pushed a import ended notification. | |
| /// | |
| /// This is useful for when `NSPersistentStoreRemoteChange` is being tracked. | |
| @State private var hasImported: Bool = false | |
| /// The externally exposed boolean variable describing how the sync state. | |
| @Binding var isSyncing: Bool | |
| func body(content: Content) -> some View { | |
| content | |
| .onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange).receive(on: DispatchQueue.main)) { _ in | |
| if !hasImported { | |
| isSyncing = true | |
| } | |
| } | |
| .onReceive(NotificationCenter.default.publisher( | |
| for: NSPersistentCloudKitContainer.eventChangedNotification | |
| ).receive(on: DispatchQueue.main)) { notification in | |
| guard let event = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey] | |
| as? NSPersistentCloudKitContainer.Event else { | |
| return | |
| } | |
| switch event.type { | |
| case .setup: | |
| print("CloudKit setup started") | |
| case .import: | |
| if event.endDate == nil { | |
| print("CloudKit Import (download) started") | |
| isSyncing = true | |
| } else { | |
| print("CloudKit Import (download) ended") | |
| isSyncing = false | |
| hasImported = true | |
| } | |
| case .export: | |
| if event.endDate == nil { | |
| print("CloudKit Export (upload) started") | |
| } else { | |
| print("CloudKit Export (upload) ended") | |
| } | |
| @unknown default: | |
| break | |
| } | |
| } | |
| } | |
| } | |
| extension View { | |
| /// A modifier that leverages several notifications to tell a bound variable if CoreData is syncing with CloudKit. | |
| public func isCoreDataSyncing(_ isSyncing: Binding<Bool>) -> some View { | |
| modifier(CoreDataIsSyncingModifier(isSyncing: isSyncing)) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment