CloudKit sync is very unstable. Sometimes it just stops syncing for no reason, other times it works almost instantly.
The core issue with synchronization is that CoreData relies mostly on two things:
- silent push notifications, which are by design unreliable and can be throttled
- user interactions, I noticed that the local database is updated most likely periodically and also based on some app events like entering the foreground.
Unfortunately, there is no SDK function that allows us to force sync with CloudKit, which basically prevents us from providing some features to recover if a user encounters problems.
After thousands of tests, I finally discovered what was wrong and how to make the synchronization stable. Basically, I noticed that at some point CoreData decides that it won't synchronize data unless you deactivate and activate the application, which is crazy. It's getting even worse if we talk about extensions like the keyboard extension on iOS. The same happens on all platforms.
Therefore, knowing that I implemented a trick that happened to work perfectly. The workaround requires to periodically sending an event pretending that the app is going foreground.
macOS:
var cancellable = Set<AnyCancellable>()
// ...
Timer.publish(every: 20.0, on: RunLoop.main, in: .common)
.autoconnect()
.sink { _ in
NotificationCenter.default.post(.init(name: NSApplication.willBecomeActiveNotification))
}
.store(in: &cancellable)
iOS:
var cancellable = Set<AnyCancellable>()
// ...
Timer.publish(every: 20.0, on: RunLoop.main, in: .common)
.autoconnect()
.sink { _ in
NotificationCenter.default.post(.init(name: UIApplication.didBecomeActiveNotification))
}
.store(in: &cancellable)
After that, everything works perfectly. Pitty that the solution mostly meant for enterprise is so unstable and there is not even a single SDK function to recover from that (force sync).
Any plans to fix CoreData+CloudKit? I also created a ticket: #FB14531806.
CloudKit sync is very unstable. Sometimes it just stops syncing for no reason, other times it works almost instantly.
When CoreData + CloudKit stops syncing, it can be that the system intentionally throttles the synchronization to balance the use of system resources and achieve the best overall user experience on the devices. To determine if that is the case and understand how the system works, you might want to read through the following technotes:
-
TN3163: Understanding the synchronization of NSPersistentCloudKitContainer
-
TN3164: Debugging the synchronization of NSPersistentCloudKitContainer
I also created a ticket: #FB14531806.
Thanks for filing the feedback report. To investigate the issue, we would need to gather more information. If you don't mind, please follow the Provide actionable feedback section to gather the appropriate information and use it to update your feedback report. That would be a great help for the team's investigation.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.