Split Core Data Entity to different stores — Part 2
As in Part 1, I covered handling double local stores in Core Data, this article will cover making a Core Data Entity sync with both CloudKit public and private database. And in next article, I will explain the limitation for this kind of setting.
These tests with iCloud connection need to run on physical devices. When running on a simulator in Xcode 14 beta 4, I got the error,
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x600002280390: “Internal Error” (1/5000); “Failed to sync user keys”>
Topic 3: Manually configure double stores in Core Data and sync with CloudKit (public/private database)
We first check what Xcode done automatically?
As long as you add the CloudKit related capability to the project, Xcode will configure the NSPersistenceContainer automatically.
Here is the basic prerequisite.
And the container type is replaced to NSPersistentCloudKitContainer.
At run time, Xcode will auto generate one NSPersistentStoreDescription which has NSPersistentCloudKitContainerOptions. In the default NSPersistentCloudKitContainerOptions, the iCloud container Identifier equals to the selected container in the project setting page. And the default database scope is private.
All these could be configured manually.
We already covered how to generate a NSPersistentStoreDescription manually, now we only need to add the CloudKit options to our description.
Now we could load the two stores with the two descriptions. Description1 connects to iCloud private database and Description2 connects to public database. And remember to NSPersistentCloudKitContainer instead of NSPersistentContainer.
And the way to insert new entities to each store respectively is the same as in Part 1.
Suppose you are going to see in the new records in the CloudKit Portal. But there is some tricky things to deal with CloudKit.
- If your Core Data schema changed, you need to run initializeCloudKitSchema()
let container : NSPersistentCloudKitContainer = getContainer()try container.initializeCloudKitSchema()
- It takes some time to sync from Core Data to iCloud. So if you are writing unit test, make thread sleep for seconds at the end of the unit test.
- On the CloudKit Portal, you need to add some extra Indexes for every Record Type which Core Data is going to sync with. Otherwise, you will get error like this,
“Field ‘___modTime’ is not marked sortable”
“Field ‘recordName’ is not marked queryable”
You need to add these three indexes for every Record Type which Core Data is going to sync with.
If all the configurations are correct, you will see records insert into private or public database as you assign them.