When I checked Used with CloudKit
, the error Folder.children must not be ordered
appeared. Any idea about an ordered relationship?
Using Xcode 11 (beta 3).
Here's the Folder
Entity:
Applies to iOS 13, and early betas of iOS 14.
Cloud kit can't use ordered relationships (which just blows, as ordered data is a fundamental Thing That Exists). The reason is that everything is backed with CKRecord
(cloud kit records) not actual core data stuff — it's a completely different type of data storage, and the PersistentCloudKitContainer
is doing on-the-fly rewrites of your data to CKRecords and back. CKRecord
s don't have mechanisms that work for maintaining journals of ordered items the way we need in Core Data ordered relationships.
Which means it's not likely to be "fixed" anytime soon, as it would require changes to CloudKit and apple's iCloud generally (vs. just changes to CoreData).
So...
You have a few not-good choices:
UUID
for each child, parent stores a concatenated list of UUID's for all children)orderIndex int
field that you maintain manually.No matter what you do, it's bad:
No relationships: no "fetch parent" and get references to children via relationship; you have to fetch both separately. Also no "delete" rules done for you, e.g. " on delete parent, cascade delete children." This works when you need children in more than one collection (as each collection record keeps it's own list of children)
Ordering in child objects (this is what I use): you have to insert yourself in every add and delete operation on children, running code to adjust orderIndex values of all children. I manage this by having a CoreDataManager.createChild(atIndex:)
, CoreDataManager.deleteChild()
and CoreDataManager.moveChild(toIndex:)
functions that apply side effect of updating orderIndex values. But at least you get "fetch parent; for c in parent.children do..." and cascade delete's back. However: now child can only be in one parent's list, as child only has one orderIndex value.
Relationship + manually maintained ordering field in parent: let core data manage the association, and when you need ordered children you can use a parent.orderedChildren()
function that reads your .childOrder
field of parent, applies it to .children list. But... you still have to manage the parent's .childOrder
field manually, and change it every time you add/remove/reorder children. HOWEVER, with Cloud Sync, there are many potential bugs wit your .child
list and .childOrder
field value getting out of sync as children are added/removed in different app instances. Keeping the child list and the ordering separate means they can be updated by cloud sync separately.