Как установить упорядоченные отношения с NSPersistentCloudKitContainer?
0 ответов
(применимо: начиная с iOS 13 и ранних бета-версий 14)
Облачный комплект не может использовать упорядоченные отношения (что просто сбивает с толку, поскольку упорядоченные данные - это фундаментальная вещь, которая существует). Причина в том, что все поддерживается CKRecord (записи облачного набора), а не фактическими основными данными - это совершенно другой тип хранилища данных, и PersistentCloudKitContainer на лету перезаписывает ваши данные в CKRecords и обратно. В CKRecords нет механизмов, которые работают для ведения журналов заказанных элементов так, как нам нужно в упорядоченных отношениях Core Data.
Это означает, что вряд ли это будет "исправлено" в ближайшее время, поскольку для этого потребуются изменения в CloudKit и iCloud от Apple в целом (а не только в CoreData).
Так...
У вас есть несколько не очень хороших вариантов:
- Не иметь формальных отношений - вместо этого имейте поле, в котором вы храните, например, список ссылок. Сохраняйте это самостоятельно при добавлении / удалении дочерних объектов. По сути, имейте поле "admin" в родительской записи, которое вы используете для поддержки собственного механизма отношений. (например: сгенерировать UUID для каждого дочернего элемента, родительский элемент хранит объединенный список UUID для всех дочерних элементов)
- Используйте CoreData Relationships и сохраните данные для заказа в дочерних объектах, например, в поле orderIndex int, которое вы поддерживаете вручную.
- Смешанный: используйте неупорядоченные отношения от родителя к потомкам, а также сохраните поле "порядок потомков" в родителе. CoreData управляет отношениями, и вы можете вручную поддерживать и применять упорядочивание этих дочерних элементов по мере необходимости.
Что бы ты ни делал, это плохо:
Нет отношений: нет "выборки родителя" и получения ссылок на потомков через отношения; вам нужно получить оба отдельно. Также для вас не применяются правила "удаления", например, "при удалении родителя, каскадное удаление потомков". Это работает, когда вам нужны дочерние элементы более чем в одной коллекции (поскольку каждая запись коллекции хранит свой собственный список дочерних элементов)
Порядок в дочерних объектах (это то, что я использую): вы должны вставлять себя в каждую операцию добавления и удаления дочерних объектов, запускать код для корректировки значений orderIndex всех дочерних элементов. Я справляюсь с этим с помощью функций CoreDataManager.createChild(atIndex:), CoreDataManager.deleteChild() и CoreDataManager.moveChild(toIndex:), которые применяют побочный эффект обновления значений orderIndex. Но, по крайней мере, вы получаете "получить родителя; для c в parent.children do..." и каскадное удаление обратно. Однако: теперь дочерний элемент может быть только в списке одного родителя, поскольку дочерний элемент имеет только одно значение orderIndex.
Отношение + вручную поддерживаемое поле упорядочивания в родительском элементе: позвольте основным данным управлять ассоциацией, а когда вам нужны упорядоченные дочерние элементы, вы можете использовать функцию parent.orderedChildren(), которая считывает ваше поле.childOrder родительского элемента и применяет его к списку.children. Но... Вам все равно придется вручную управлять родительским полем.childOrder и изменять его каждый раз, когда вы добавляете / удаляете / меняете порядок дочерних элементов. ОДНАКО с Cloud Sync существует множество потенциальных ошибок, связанных с рассинхронизацией вашего списка.child и значения поля.childOrder по мере добавления / удаления дочерних элементов в разных экземплярах приложения. Разделение дочернего списка и упорядочивания означает, что их можно обновлять с помощью облачной синхронизации отдельно.