Сохраняйте автономные изменения отдельно от исходных данных в Core Data

Я добавляю функцию "автономного режима" в приложение, над которым сейчас работаю. По сути, идея состоит в том, что пользователи должны иметь возможность вносить изменения в данные, например, редактировать описание элемента, без подключения к Интернету, и изменения должны сохраняться между запусками приложений.

Каждое изменение обычно приводит к запросу API при работе в сети, но в автономном режиме ситуация иная.

Сейчас это реализовано путем хранения всех данных, поступающих из API, в базе данных Core Data, которая действует как кеш. Сущности, которые может редактировать пользователь, помимо обычных атрибутов, имеют следующие:

  • locallyCreated - был ли объект создан офлайн
  • locallyDeleted - объект удален офлайн
  • locallyUpdated - обновлено

Это позволяет искать новые / удаленные / обновленные объекты и отправлять соответствующие запросы API при выполнении синхронизации.

Это хорошо сработало для создания и удаления объектов, однако один недостаток, который я обнаружил в этом подходе, заключается в том, что когда новые данные извлекаются из API, все локальные изменения (то есть атрибуты объектов, отмеченных как локально обновленные) теряются, что означает, что они должны быть отдельно хранится как-то.

Как лучше всего подойти к этой проблеме?


person iosdude    schedule 16.05.2016    source источник


Ответы (1)


Поскольку у вас есть ключ locallyUpdated, очевидным ответом является изменение кода, который импортирует изменения сервера, чтобы он не перезаписывал изменения любого объекта, помеченного как измененный. Так или иначе, вам нужно избегать перезаписи этих изменений, и вы уже ведете запись о том, какие объекты имеют изменения, так что у вас уже есть инструменты для базового решения.

Но вскоре вы столкнетесь со сложностью синхронизации данных. Что, если у локального объекта есть изменения на одном ключе, но входящие данные с сервера имеют изменения на другом ключе? Вы не можете решить эту проблему, просто зная, что локальная копия каким-то образом изменилась. Может быть, вы решите, что всегда побеждает сервер или всегда побеждает локальная копия. Это легко, если они имеют смысл для вашего приложения. Однако, если вам нужно объединить изменения, у вас впереди есть работа. Вам нужно будет записать не только логическое значение, указывающее, что были внесены изменения, но и список того, какие ключи были изменены. Это может быть сложно, но такова природа синхронизации данных.

person Tom Harrington    schedule 16.05.2016
comment
Я думал о сохранении словаря с измененными свойствами и их значениями, но тогда мне нужно было бы как-то настроить все обращения к свойствам, чтобы сначала смотреть на обновленные значения, а только потом на фактические атрибуты NSManagedObject. Честно говоря, я немного потерялся прямо сейчас, я как бы продолжаю думать, что это можно сделать с помощью политик слияния Core Data, но я никогда не работал с ними, поэтому я даже не знаю, сработает ли это. Думаю, придется поэкспериментировать. Спасибо! - person iosdude; 17.05.2016
comment
Вместо изменения аксессуаров может помочь описанная здесь стратегия: stackoverflow.com/questions/23433838/ - person Tom Harrington; 17.05.2016
comment
Забавно, вчера я погуглил этот ответ :) Кажется, это правильный путь. - person iosdude; 18.05.2016
comment
Вы знаете, как отменить изменения определенных свойств внутри обработчика NSManagedObjectContextObjectsDidChangeNotification? Простая установка для них старых значений вызывает повторное срабатывание того же уведомления, поэтому необходим механизм защиты, чтобы избежать бесконечной рекурсии. Я подозреваю, что есть более простой способ сделать это ... - person iosdude; 18.05.2016
comment
Нет, потому что это не является этапом проверки. В этот момент значение уже изменилось, поэтому отмена его на самом деле означает внесение нового изменения, которое вернется к предыдущему значению. Если вам нужно проверить значения, это может потребоваться в методах доступа. - person Tom Harrington; 18.05.2016