Я работаю над синхронизацией данных между клиентом и сервером. Я использую MagicalRecord
(обертка основных данных) для хранения данных на клиенте. У меня есть объект под названием Dirty
, который содержит один атрибут, называемый dirty
. Это означает, что на клиенте были изменения, которые еще не были перенесены на сервер. dirty
получает значение [NSDate date]
в любое время, когда атрибут установлен в классе (конечно, при установке dirty
задано правильное значение). Каждый другой объект, созданный на клиенте, наследует от Dirty
. Идея состоит в том, что мы не будем извлекать новые данные с сервера, пока все клиентские данные не будут оттолкнуты (только для получения новых данных, если все объекты имеют dirty == nil
).Использование грязного флага с базовыми данными для синхронизации с сервером
При импорте данных с сервера (с помощью +[NSManagedObject MR_importFromObject:inContext:
), атрибут каждого лица dirty
получает значение nil
(так как клиент уточненный с сервером).
Перед тем, как сэкономлено сбережение (внутри блока сохранения +[MagicalRecord saveWithBlock:completion:]
), dirty
по-прежнему nil
. Однако в блоке завершения выборка объекта, который только что был сохранен (в основном потоке), имеет значение для dirty
.
Во время сохранения объект переносится в контекст основного потока. Однако есть проблема, потому что -[NSManagedObject didChangeValueForKey:]
вызывается для каждого атрибута, который передается из localContext
(фоновый поток) в основной контекст (в основном потоке). dirty
устанавливается с [NSDate date]
для каждого объекта. Большую часть времени dirty
не получает последний набор, что означает, что когда установлен другой атрибут, dirty
перезаписывается.
Есть ли способ убедиться, что dirty
- последний атрибут, который задается при передаче экземпляра NSManagedObject в контекст основного потока? Я даже хочу установить dirty
, когда объект будет сохранен (вместо того, когда будут установлены свойства).
Я пробовал всевозможные варианты, включая проверку против -[NSManagedObject isInserted]
и -[NSManagedObject isUpdated]
внутри -[NSManagedObject didChangeValueForKey:]
. Еще одна вещь, которая вызывает раздражение, заключается в том, что новый объект вставлен перед передачей атрибутов (я думал, что у меня может быть какой-то флаг для блокировки/разблокировки dirty
).
Еще одна вещь, которую следует отметить: [NSManagedObject(_NSInternalMethods) _updateFromRefreshSnapshot:includingTransients:]
- это то, что вызывается прямо перед тем, как -[NSManagedObject didChangeValueForKey:]
вызывается на новый объект.
Любые идеи? Я уже пару дней обманывал это.
Так что я уже делаю это с 'clientUpdatedAt' (и' clientCreatedAt'). 'clientUpdatedAt' не является достаточно хорошим показателем, потому что, когда сервер обновляет объект на клиенте с помощью' updatedAt'time сервера, сущность должна сохранять, а 'clientUpdatedAt' обновляется с' + [NSDate date] 'еще раз. Если я проверю, является ли 'clientUpdatedAt' более поздним, чем' updatedAt', он будет возвращать 'YES' каждый раз. :/ – Jeff
Я обновил свой ответ, вам может потребоваться ввести больше атрибутов для обработки синхронизации. – Olaf
Спасибо за обновление вашего ответа. Задача заключается в следующем: «установите sync_status в 1 на объект модели, когда что-то изменится и его необходимо синхронизировать с сервером». Это та же проблема, что и в моем коде. Я попытался использовать 'didChangeValueForKey:', но это было ненадежным по причинам, упомянутым в моем первоначальном сообщении. Есть ли у вас предложения по выполнению этого шага? Как только это выяснится, все остальное будет плавным. – Jeff