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