App unresponsive when calling record(for:) on NSPersistentCloudKitContainer

I'm experiencing an unresponsive UI since MacOS 14.0 and iOS 17.0 when calling record(for: ) or recordID(for:) on the instance of NSPersistentCloudKitContainer.

On MacOS, the UI freeze almost always happens when calling the function.

On iOS, it is necessary that the device (or simulator) does not have any network connection.

I would like to ask if anyone experienced the same problem. I have posted the problem twice to Apple via the Feedback app (once for iOS and once for MacOS). No reply yet on MacOS but on iOS Apple marked it as resolved because apparently no one but me has experienced this problem.

In the meantime, I have set up a minimum reproducible example app (MRE).:

https://github.com/DominikButz/NotesApp-Cloud-Kit-Record-UI-Freeze-

Anyone interested, please read the readme of the repository. It includes step by step instructions on how to reproduce the bug.

I can't rule out I have misunderstood the usage of CoreData and CloudKit - in that case please point me in the right direction.

The app I'm working on should also work offline (and on MacOS!) but it doesn't do so properly as long as this bug exists.

I'm exploring switching to SwiftData (which would mean no one using macOS 13 / iOS 16 can use my app...) but I would still need to access cloud kit records even with SwiftData and I fear the bug also exists in SwiftData.

Thanks

Answered by Frameworks Engineer in 779569022

So... the root cause of this issue is that you're calling recordID(for:) on the main thread during container setup (it looks like there is a fairly substantial import at the time you call it).

NSPersistentCloudKitContainer can't concurrently serialize records and perform other work. You could file an enhancement request for that, but that would come with other consequences (like cache-miss issues for records that are in the process of being serialized).

You can move this call to a background queue to avoid blocking the main thread's run loop on this work.

As an aside, it looks like you're attempting to use the CKRecordID to coordinate data across multiple sync mechanisms. This is unlikely to lead to success. While it is exceedingly rare NSPersistentCloudKitContainer reserves the right to change the recordID for a managed object. We recommend that clients invent a foreign key of their own that they can pass to the other sync mechanism as a way of tracking related data.

Can you share your feedback IDs?

thanks for your reply. The feedback IDs are FB13284132 and FB13473137.

Accepted Answer

So... the root cause of this issue is that you're calling recordID(for:) on the main thread during container setup (it looks like there is a fairly substantial import at the time you call it).

NSPersistentCloudKitContainer can't concurrently serialize records and perform other work. You could file an enhancement request for that, but that would come with other consequences (like cache-miss issues for records that are in the process of being serialized).

You can move this call to a background queue to avoid blocking the main thread's run loop on this work.

As an aside, it looks like you're attempting to use the CKRecordID to coordinate data across multiple sync mechanisms. This is unlikely to lead to success. While it is exceedingly rare NSPersistentCloudKitContainer reserves the right to change the recordID for a managed object. We recommend that clients invent a foreign key of their own that they can pass to the other sync mechanism as a way of tracking related data.

App unresponsive when calling record(for:) on NSPersistentCloudKitContainer
 
 
Q