Как синхронизировать CoreData, и веб-сервис REST асинхронно и то же время правильно распространяет любые ошибки REST в UI

Эй, я работаю над образцовым слоем для нашего приложения здесь.

Некоторые требования похожи на это:

  1. Это должно работать над iPhone OS 3.0 +.
  2. Источник наших данных является УСПОКОИТЕЛЬНЫМ приложением направляющих.
  3. Мы должны кэшировать данные локально с помощью Базовых Данных.
  4. Клиентский код (наши контроллеры UI) должен иметь как можно меньше знания о любом сетевом материале и должен запросить/обновить модель с Базовыми Данными API.

Я проверил Сессию WWDC10 117 на Создание управляемого Сервером Пользовательского Опыта, провели некоторое время, проверяя Объективный Ресурс, Базовый Ресурс и платформы RestfulCoreData.

Объективная платформа Ресурса не говорит с Базовыми Данными самостоятельно и является просто клиентской реализацией REST. Базовый Ресурс и RestfulCoreData, все принимают Вас, говорят с Базовыми Данными в Вашем коде, и они решают все основные детали в фоновом режиме на образцовом слое.

Все взгляды хорошо до сих пор и первоначально я, хотя или Базовый Ресурс или RestfulCoreData покроют все указанные выше требования, но... Существует несколько вещей, которые ни один из них по-видимому, оказывается, не решает правильно:

  1. Основной поток не должен быть заблокирован при сохранении локальных обновлений сервера.
  2. Если операция сохранения перестала работать, ошибка должна быть распространена к UI, и никакие изменения не должны быть сохранены к локальному Базовому Хранению данных.

Базовый Ресурс, оказывается, выпускает все свои запросы к серверу, когда Вы звоните - (BOOL)save:(NSError **)error на Вашем Контексте Управляемого объекта и поэтому может обеспечить корректный экземпляр NSError базовых запросов к сбою сервера так или иначе. Но это блокирует вызывающий поток, пока операция сохранения не заканчивается. СБОЙ.

RestfulCoreData сохраняет Ваш -save: называет неповрежденным и не представляет дополнительного времени ожидания клиентского потока. Это просто не упускает NSManagedObjectContextDidSaveNotification и затем выпускает соответствующие запросы к серверу в обработчике уведомлений. Но этот путь -save: вызов всегда завершается успешно (хорошо, учитывая Базовые Данные хорошо с сохраненными изменениями), и клиентский код, который на самом деле звонил, это не имеет никакого способа знать, что сохранение, возможно, не распространило к серверу из-за некоторых 404 или 421 или независимо от того, что ошибка серверной стороны произошла. И еще больше, локальное устройство хранения данных становится, чтобы обновить данные, но сервер никогда не знает об изменениях. СБОЙ.

Так, я ищу возможное решение / общие методы имея дело со всеми этими проблемами:

  1. Я не хочу, чтобы вызывающий поток заблокировался на каждом -save: звоните, в то время как сетевые запросы происходят.
  2. Я хочу так или иначе получить уведомления в UI, что некоторая синхронизирующая операция пошла не так, как надо.
  3. Я хочу фактические Базовые Данные, сохраняют сбой также, если запросы к серверу перестали работать.

Какие-либо идеи?

84
задан eploko 8 May 2012 в 12:37
поделиться

2 ответа

Вам нужна функция обратного вызова, которая будет запускаться в другом потоке (том, где происходит фактическое взаимодействие с сервером), а затем поместить код результата / информацию об ошибке в полуглобальные данные, которые будут периодически проверяться потоком пользовательского интерфейса. Убедитесь, что wirting числа, которое служит флагом, является атомарным, или у вас будет состояние гонки - скажем, если ваш ответ об ошибке составляет 32 байта, вам нужен int (который должен иметь атомарный доступ), а затем вы сохраните этот int в выключенном / ложном / неготовом состоянии до тех пор, пока ваш больший блок данных не будет записан, и только затем напишите «истина», чтобы, так сказать, щелкнуть переключатель.

Для коррелированного сохранения на стороне клиента вы должны либо просто сохранить эти данные, а не сохранять их, пока не получите подтверждение от сервера, либо убедитесь, что у вас есть опция отката - скажем, способ удаления - это сбой сервера .

Помните, что это никогда не будет на 100% безопасным, если вы не выполните полную двухэтапную процедуру фиксации (сохранение или удаление клиента может завершиться ошибкой после сигнала с сервера-сервера), но это будет стоить вам двух поездок на сервер в по крайней мере (может стоить вам 4, если ваш единственный вариант отката - удаление).

В идеале вам следует выполнить всю блокирующую версию операции в отдельном потоке, но для этого вам понадобится 4.0.

0
ответ дан 24 November 2019 в 08:39
поделиться

Это становится проблемой синхронизации, которую нелегко решить. Вот что я бы сделал: в пользовательском интерфейсе вашего iPhone используйте один контекст, а затем, используя другой контекст (и другой поток), загрузите данные из вашего веб-сервиса. Как только все будет готово, выполните процессы синхронизации / импорта, рекомендованные ниже, а затем обновите пользовательский интерфейс после того, как все будет импортировано должным образом. Если что-то пойдет не так при доступе к сети, просто откатите изменения в контексте, отличном от пользовательского интерфейса. Это куча работы, но я думаю, что это лучший подход к ней.

Основные данные: эффективный импорт данных

Основные данные: управление изменениями

Основные данные: многопоточность с основными данными

2
ответ дан 24 November 2019 в 08:39
поделиться