Igor R.
Igor R.

Reputation: 429

How to call WidgetCenter.shared.reloadAllTimelines() when Core Data in CloudKit changes?

I have an app that uses Core Data with CloudKit. Changes are synced between devices. Main target has Background Modes capability with checked Remote notifications, iCloud capability is checked with Services set to CloudKit and correct container in Containers checked.

How can I react in code to changes, deleting, and addition of records? I need to call WidgetCenter.shared.reloadAllTimelines() when Core Data in CloudKit changes to update iOS 14 homescreen widget.

My goal is to get this working: I change/add/delete record on icloud.developer.apple.com or another device, and WidgetCenter.shared.reloadAllTimelines() called to display correct data in widget. App may be in background or foreground.

From AppDelegate.swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Register for Remote Notifications
    application.registerForRemoteNotifications()
    
    return true
}

Also, noticed messages in output log:

CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate remoteStoreDidChange:]_block_invoke(2138): <NSCloudKitMirroringDelegate: 0x281818d00> - Ignoring remote change notification because the exporter has already caught up to this transaction: 64 / 64 - <NSSQLCore: 0x100b09440> (URL: file:///var/mobile/Containers/Data/Application/F83C68DA-7C36-42CC-926D-7C721C679579/Library/Application%20Support/AppTitle.sqlite)

Upvotes: 4

Views: 3450

Answers (1)

pawello2222
pawello2222

Reputation: 54426

If you want to subscribe to Core Data remote notifications you can use onReceive:

struct WidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        Text(entry.date, style: .time)
            .onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
                // make sure you don't call this too often
                WidgetCenter.shared.reloadAllTimelines()
            }
    }
}

Just make sure you don't call reloadAllTimelines() too often - there likely is a limited number of updates available to your widget.

Upvotes: 6

Related Questions