Подтвердить что ты не робот

ICloud + CoreData - как избежать дублирования дублированных данных?

У меня проблема с приложением 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, правильно синхронизируются.

4b9b3361

Ответ 1

Стратегия 1 с некоторыми изменениями оказалась рабочим решением (с некоторыми недостатками).

Условные обозначения:

  • 1st device - началось онлайн без какого-либо контента в iCloud
  • 2nd device - запускается позже первого и OFFLINE. Затем он становится онлайн после добавления некоторых элементов.

Итак, обновленная стратегия:

  • Во всех моих категориях создаются метки времени

  • Категории не могут быть переименованы (добавлены или удалены - это очень важно)

  • Все мои объекты имеют поле categoryName строки, которое получает свое значение при создании элемента и обновляется всякий раз, когда элемент перемещается в другую категорию - эта избыточная информация помогает добиться успеха;

При вставке новых категорий:

  • При вставке из iCloud я получаю пары категорий с одинаковым именем, если есть

  • Выберите более новые повторяющиеся категории (у них, скорее всего, будет меньше предметов, чем у старых, поэтому у нас будет меньше танец в iCloud)

  • Переместите свои элементы, если они есть, в старые повторяющиеся категории

  • Удалить более новые повторяющиеся категории

При вставке новых Элементов - если элемент принадлежит категории удален:

  • CoreData пытается объединить его, а не удается, поскольку нет родительской категории (много ошибок в консоли). Он обещает вставить его позже.

  • Через некоторое короткое время он объединяется и вставляет элемент в хранилище, но с NIL категория

  • Здесь мы выбираем наш элемент вверх, узнаем его родительскую категорию из categoryName и помещаем в нужную категорию

VOILA! - нет дубликатов и всех счастливых

Несколько примечаний:

  • Я получаю танец предметов, принадлежащих 2-му устройству (те, которые будут поставляться с нулевой категорией к 1-му устройству) на обоих устройствах. Через пару минут все стабилизируется.
  • Ничего не потеряно, но
  • Танец происходит только при первой синхронизации iCloud второго (или любого другого последующего устройства).
  • Если второе устройство запускается онлайн в первый раз, вероятность того, что случай с дублирующимися категориями будет отображаться только на 25% - протестирован на 3G-соединении - так что танец не должен влиять на большинство пользователей li >