Как синхронизировать таблицу CoreData с онлайн-ресурсом?

У меня есть список элементов на моем сервере, копия которых у моего приложения есть в CoreData.

Один из моих веб-API загружает актуальный список.

Я успешно написал код, который обновляет столбцы и добавляет новые строки/элементы в мое локальное хранилище CoreData. Вот код для обработки элемента, полученного с сервера («имя» однозначно идентифицирует строку, предположим, что Object — это сущность):

NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setPredicate:[NSPredicate predicateWithFormat:@"name == %@", dictionary[@"name"]]];
[request setEntity:[NSEntityDescription entityForName:@"Object"
                               inManagedObjectContext:managedObjectContext]];

error = nil;
ObjectData* object = [[managedObjectContext executeFetchRequest:request error:&error] lastObject];
//### Handle error.
if (object == nil)
{
    object = (ObjectData*)[NSEntityDescription insertNewObjectForEntityForName:@"Object"
                                                        inManagedObjectContext:managedObjectContext];
}

object.name  = dictionary[@"name"];
object.place = dictionary[@"place"];
...

error = nil;
[managedObjectContext save:&error];
//### Handle error.

Приведенный выше код синхронизирует существующие и новые элементы с сервера в CoreData. Однако строки, которые были удалены на сервере, не удаляются из CoreData.

Каков эффективный способ синхронизации удалений? Примечание. У Objects есть отношения, поэтому простое удаление всего лота и добавление их снова не сработает.

Например, как сформировать запрос, удаляющий все строки, имя которых отсутствует в загруженном списке обновлений?


person meaning-matters    schedule 02.09.2013    source источник


Ответы (1)


Если данные сервера всегда представляют полную таблицу, не беспокойтесь о логике синхронизации, просто замените данные клиента.

Если это действительно ситуация синхронизации, рассмотрите возможность использования «обратимого удаления». Добавьте столбец даты «deletedAt» в таблицы сервера и клиента и синхронизируйте его. Квалифицируйте клиентские запросы так, как они у вас есть, но добавьте deleteAt != nil. Время от времени (как на клиенте, так и на сервере) удаляйте строки, где deleteAt старше какой-то старой даты.

Дополнительным преимуществом этого является возможность отменить удаление за некоторое время до установленного вами старого порога даты.

В качестве альтернативы, чтобы найти объекты в ваших данных, которых нет в загруженных объектах:

NSArray *names = // the array of names in the newly loaded data
NSPredicate *deletedPredicate = [NSPredicate predicateWithFormat:@"NOT (name IN %@)",names];
person danh    schedule 02.09.2013
comment
Спасибо за быстрый ответ! Приложению не требуется такое мягкое удаление, потому что настоящие данные находятся на сервере. Таким образом, это добавит ненужной работы и сложности. Возможно, вы знаете, как я могу сформировать запрос, который удалит все элементы с именами, которых нет в недавно загруженном списке имен? - person meaning-matters; 02.09.2013
comment
Такой запрос кажется выполнимым, но как вы можете быть уверены, что отсутствующее имя во вновь загруженном списке действительно представляет собой удаление? Возможно, он просто не появился в результатах запроса. Если ответ заключается в том, что недавно загруженный список всегда представляет всю таблицу, то вам вообще не нужна какая-либо логика синхронизации. Просто замените данные клиента только что загруженным списком. - person danh; 02.09.2013
comment
Да, загруженный список всегда полный. Как мне «заменить» список клиентов, кроме как сначала удалив старый? Я беспокоюсь, что это удаление разрушит отношения. Ах, но подождите, с вашим deletePredicate я прозреваю! Да, это так, спасибо! - person meaning-matters; 02.09.2013