У меня проблема с приложением iCloud для обувной коробки, и я надеюсь, что кто-нибудь сможет мне помочь (я потратил много часов на борьбу с этим напрасно).
Приложение: - Простое приложение в стиле библиотеки, содержащее набор категорий (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 - вставляются предварительно заполненные категории.
К вашему сведению - я использую NSMergeByPropertyObjectTrumpMergePolicy для моего ManagedObjectContext
Проблема: Это хорошо работает для 1-го устройства. Но для 2-го устройства категории по умолчанию из iCloud часто принимаются позже, чем был установлен persistentStoreCoordinator (и категории по умолчанию, вставленные 2-м устройством).В итоге у меня есть 2 набора категорий с одинаковыми именами на обоих устройствах.
Есть идеи, как это можно решить?
Пробные решения: Я пробовал 2 стратегии, чтобы решить эту проблему. Оба начинаются одинаково. После того, как я позвоню
[moc mergeChangesFromContextDidSaveNotification: note];
, я позвоню
[self materializeKeysWithUserInfo: note.userInfo forContext: moc];
, большое спасибо Хосе Инес Канту Аррамбиде из https://devforums.apple.com/thread/126670?start=400&tstart=0 за его ссылочный код - In сущность
materializeKeysWithUserInfo:forContext:
получает ManagedObjectIds из note.userInfo и извлекает соответствующие объекты из ManagedObjectContext, помещая их в словарь.
Стратегия 1:
Эта стратегия эффективно удаляет дубликаты на оба устройства еще до того, как они появятся в пользовательском интерфейсе НО
1) элементы с 1-го устройства теряются на 2-м устройстве - когда они переходят на 2-е устройство, их родительская категория отсутствует, а их поле категории равно нулю, поэтому Я не знаю, куда их положить.
2) через некоторое время предметы, потерянные на 2-м устройстве, также теряются на первом из-за конфликтов.
3) некоторые элементы, исходящие от 2-го устройства, также потеряны из-за конфликтов.
Я пытался предпочесть старые категории новым, но это не дало никакого эффекта
Стратегия 2:
Эта стратегия почти всегда удаляет дубликаты на обоих устройствах даже до того, как они появятся в пользовательском интерфейсе НО
большинство (или все) элементы с обоих устройств теряются из-за множества конфликтов по категориям и элементам.
Некоторые заключительные мысли:
Похоже, эта стратегия не работает, поскольку мы начинаем одновременно изменять контент на обоих устройствах, тогда как iCloud не подходит для такой схемы.
В моих тестах оба устройства работали одновременно. Я не могу игнорировать случай, когда счастливый пользователь, который только что купил свое 2-е iDevice, устанавливает мое приложение на 2-е устройство (с Tre 1-м устройством, на котором запущено приложение) и теряет все свои элементы в считанные минуты.
Есть идеи, как можно разрешить эту ситуацию? Как вы думаете, iCloud + CoreData готов к производству?
Стратегия 3
Я попытался поместить предварительно заполненную базу данных (скопировав ее из пакета) по соответствующему пути. Частично это сработало - у меня больше нет дублирования предварительно заполненных категорий НО элементы, добавленные в предварительно заполненные категории, не синхронизируются на устройствах.
iCloud не знает данных, которые существовали в базе данных до настройки iCloud - мое 2-е устройство получает элементы, вставленные на 1-е устройство в предварительно заполненных категориях, с категорией = nil.
Элементы в дополнительных категориях (а также сами категории), вставленные в хранилище после настройки iCloud, синхронизируются должным образом.