У меня проблема с приложением iCloud shoebox и надеюсь, что кто-то может мне помочь (я провел много часов, борясь с ним зря).
Приложение: - простое приложение стиля библиотеки - содержит набор категорий (Cat1.. CatN), каждый из которых содержит элементы (Item1... ItemM). Я использовал Apple iPhoneCoreDataRecipes для настройки стека iCloud CoreData.
Все работает почти отлично с iCloud за исключением - должно быть множество предварительно заполненных пустых категорий, которые пользователь может начать использовать, как только он открыл приложение в первый раз (он также может быть в автономном режиме в это время). И вот дьявол.
Вот что я делаю - как только мой persistentStoreCoordinator настроен, я отправляю уведомление
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter]
postNotificationName: @"RefetchAllDatabaseData"
object: self
userInfo: nil];
});
который получен моим MasterViewController. Когда уведомление получено, MasterViewController проверяет количество категорий в хранилище. Если количество доступных категорий равно 0 - вставляются предварительно заполненные категории.
FYI - я использую NSMergeByPropertyObjectTrumpMergePolicy для моего ManagedObjectContext
Проблема: Это хорошо работает для 1-го устройства. Но для второго устройства категории по умолчанию из iCloud часто принимаются позже, чем persistentStoreCoordinator был настроен (и категории по умолчанию, вставленные вторым устройством). В итоге у меня есть два набора категорий с одинаковыми именами на обоих устройствах.
Любые идеи, как это можно решить?
Пробованные решения: Я попытался решить две стратегии. Оба начинаются одинаково. После того, как я позвоню
[moc mergeChangesFromContextDidSaveNotification: note];
Я звоню
[self materializeKeysWithUserInfo: note.userInfo forContext: moc];
большое спасибо Jose Ines Cantu Arrambide от https://devforums.apple.com/thread/126670?start=400&tstart=0 для своего ссылочного кода - По существу
materializeKeysWithUserInfo:forContext:
получить managedObjectIds из note.userInfo и получить соответствующие объекты из ManagedObjectContext, помещая их в словарь.
Стратегия 1:
- Во всех моих категориях есть метки времени создания.
- Вставить из iCloud, получить пары категорий с одинаковым именем, если есть
- Выберите более старые повторяющиеся категории
- перемещать свои объекты в более новые повторяющиеся категории.
- удалить старые повторяющиеся категории
Эта стратегия эффективно удаляет дубликаты на обоих устройствах еще до того, как они появятся в интерфейсе пользователя НО
1) предметы с 1-го устройства теряются на 2-м устройстве - когда они поступают на второе устройство, их родительская категория отсутствует, а поле их категории равно нулю, поэтому я не знаю, где их поставить.
2) за короткое время предметы, потерянные на втором устройстве, также теряются на первом из-за конфликтов.
3) некоторые элементы, происходящие из 2-го устройства, также теряются из-за конфликтов.
Я пытался предпочесть более старые категории против новее, но это не дало эффекта
Стратегия 2:
- Во всех моих категориях есть метки времени создания.
- Все категории имеют устаревшее логическое поле, установленное в NO при создании
- Вставить из iCloud, получить пары категорий с одинаковым именем, если есть
- Выберите более старые повторяющиеся категории
- перемещать свои объекты в более новые повторяющиеся категории.
- отметьте более старые категории с устаревшим = YES
Эта стратегия почти всегда удаляет дубликаты на обоих устройствах еще до того, как они появятся в интерфейсе пользователя НО
большинство (или все) элементов с обоих устройств теряются из-за кучки конфликтов по категориям и элементам.
Некоторые заключительные мысли:
Похоже, что эта стратегия не работает, поскольку мы запускаем одновременное изменение содержимого обоих устройств, тогда как iCloud не подходит для такого шаблона.
В моих тестах у меня одновременно работало оба устройства. Я не могу игнорировать случай, когда счастливый пользователь, который только что купил его 2-й iDevice, устанавливает мое приложение на 2-ом устройстве (с первым устройством, использующим приложение), и потерял все свои предметы за считанные минуты.
Любые идеи, как эта ситуация может быть решена? Как вы думаете, iCloud + CoreData готов к производству?
Стратегия 3
Я попытался поместить предварительно заполненную базу данных (скопировать ее из пакета) в соответствующий путь. Это частично сработало - у меня больше нет дублированных категорий. НО элементы, добавленные в предварительно заполненные категории, не синхронизируются между устройствами.
iCloud не знает данные, которые существуют в базе данных до установки iCloud - мое второе устройство получает элементы, вставленные на 1-е устройство в предварительно заполненных категориях, с категорией = nil.
Элементы дополнительных категорий (а также сами категории), вставленные в хранилище после настройки iCloud, правильно синхронизируются.