Как синхронизировать основные данные iPhone с веб-сервером, а затем нажать на другие устройства? [закрытый]

Я работаю над методом синхронизации основных данных, хранящихся в приложении iPhone, между несколькими устройствами, такими как iPad или Mac. Существует не так много (если вообще есть) фреймворков синхронизации для использования с основными данными в iOS. Тем не менее, я думал о следующем понятии:

  1. в локальное хранилище основных данных вносится изменение, которое сохраняется. (a) если устройство подключено, оно пытается отправить набор изменений на сервер, включая идентификатор устройства который отправил набор изменений. (b) если набор изменений не доходит до сервера или устройство не подключено к сети, приложение добавит набор изменений в очередь для отправки, когда он выйдет в сеть.
  2. сервер, сидящий в облаке, объединяет определенные наборы изменений, которые он получает, со своей основной базой данных.
  3. после объединения набора изменений (или очереди наборов изменений) на облачном сервере сервер отправляет все эти наборы изменений на другие устройства, зарегистрированные на сервере, используя некоторые сортировка избирательных систем. (Я думал использовать Push-сервисы Apple, но, по-видимому, согласно комментариям, это не работоспособная система.)

есть ли что-нибудь необычное, о чем мне нужно думать? Я посмотрел на рамки отдыха, такие как ObjectiveResource, Основной Ресурс и RestfulCoreData. Конечно, все они работают с Ruby on Rails, к которым я не привязан, но это место для начала. Основные требования I для моего решения:

  1. любые изменения должны быть отправлены в фоновом режиме, не отвлекаясь от основного потока.
  2. Он должен использовать как можно меньше пропускной способности.

Я подумал о ряде проблем:

  1. убедитесь, что идентификаторы объектов для разных хранилищ данных на разных устройствах подключены к серверу. То есть, у меня будет таблица идентификаторов объектов и идентификаторов устройств, которые связаны через a ссылка на объект, хранящийся в базе данных. У меня будет запись (DatabaseId [уникальный для этой таблицы], ObjectId [уникальный для элемента во всей базе данных], Datafield1, Datafield2), поле ObjectId будет ссылаться на другую таблицу, AllObjects: (ObjectId, DeviceId, DeviceObjectId). Затем, когда устройство выдвигает набор изменений, оно передает идентификатор устройства и objectId из объекта core data в локальном хранилище данных. Затем мой облачный сервер проверит objectId и идентификатор устройства в таблица AllObjects и найдите запись для изменения в исходной таблице.
  2. все изменения должны быть помечены временем, чтобы их можно было объединить.
  3. устройство должно будет опросить сервер, не используя слишком много батареи.
  4. локальным устройствам также потребуется обновить все, что хранится в памяти, если / когда изменения получены с сервера.

что-то еще я упускаю? Какие рамки я должен посмотреть, чтобы сделать это возможно?

9 ответов


Я предлагаю внимательно прочитать и реализовать стратегию синхронизации, обсуждаемую Дэном Гровером на конференции iPhone 2009, доступно здесь в формате pdf.

Это жизнеспособное решение и не так сложно реализовать (Dan реализовал это в нескольких своих приложениях), перекрывая решение, описанное Крисом. Для углубленного теоретического обсуждения синхронизации см. статью Расса Кокса (MIT) и Уильяма Джозефсона (Принстон):

синхронизация файлов с векторными парами времени

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

EDIT:

похоже, что pdf-файл Grover больше не доступен (сломанная ссылка, март 2015). Обновление: ссылка доступна через Обратную машину здесь

фреймворк Objective-C называется zsync выступает и разработанный Маркусом Заррой был устаревшим, учитывая, что iCloud, наконец, поддерживает правильную синхронизацию основных данных.


Я сделал что-то похожее на то, что ты пытаешься сделать. Позвольте мне рассказать вам, что я узнал и как я это сделал.

Я предполагаю, что у вас есть отношение "один к одному" между вашим основным объектом данных и моделью (или схемой БД) на сервере. Вы просто хотите синхронизировать содержимое сервера с клиентами, но клиенты также могут изменять и добавлять данные. Если я правильно понял, продолжай читать.

Я добавил четыре поля, чтобы помочь с синхронизация:

  1. sync_status - добавьте это поле только в основную модель данных. Он используется приложением, чтобы определить, есть ли у вас ожидающие изменения в элементе. Я использую следующие коды: 0 означает отсутствие изменений, 1 означает, что он находится в очереди для синхронизации с сервером, а 2 означает, что это временный объект и может быть очищен.
  2. is_deleted - добавьте это к модели данных сервера и ядра. Событие Delete не должно фактически удалять строку из база данных или из вашей клиентской модели, потому что она не оставляет вам ничего для синхронизации. Имея этот простой логический флаг, вы можете установить is_deleted в 1, синхронизировать его, и все будут счастливы. Вы также должны изменить код на сервере и клиенте для запроса номера удаленные с "is_deleted=0".
  3. last_modified - добавьте это к модели данных сервера и ядра. Это поле должно автоматически обновляться сервером с указанием текущей даты и времени в этой записи все меняется. Он никогда не должен быть изменен клиентом.
  4. guid - добавить глобальный уникальный идентификатор (см. http://en.wikipedia.org/wiki/Globally_unique_identifier) поле для модели данных сервера и ядра. Это поле будет первичным ключом и становится важным при создании новых записей на клиенте. Обычно первичный ключ является увеличивающимся числом на сервере, но мы должны иметь в виду, что контент может быть создан в автономном режиме и синхронизируется позже. GUID позволяет нам создавать ключ в автономном режиме.

на клиенте добавьте код для установки sync_status в 1 на объекте модели всякий раз, когда что-то меняется и должно быть синхронизировано с сервером. Новые объекты модели должны генерировать GUID.

синхронизация-это один запрос. Запрос содержит:

  • максимальная отметка времени last_modified объектов модели. Это говорит серверу, что вы хотите только изменений после этого времени штамп.
  • массив JSON, содержащий все элементы с sync_status=1.

сервер получает запрос и делает это:

  • он берет содержимое из массива JSON и изменяет или добавляет содержащиеся в нем записи. Поле last_modified обновляется автоматически.
  • сервер возвращает массив JSON, содержащий все объекты с отметкой времени last_modified больше, чем отметка времени, отправленная в запросе. Эта воля включите только что полученные объекты, которые служат подтверждением успешной синхронизации записи с сервером.

приложение получает ответ и делает это:

  • он берет содержимое из массива JSON и изменяет или добавляет содержащиеся в нем записи. Каждая запись получает набор sync_status 0.

надеюсь, это поможет. Я использовал слово "запись" и "модель" взаимозаменяемо, но я думаю, вы поняли идею. Хороший удача.


Если вы все еще ищете способ пойти, посмотрите в Couchbase mobile. Это в основном делает все, что вы хотите. (http://www.couchbase.com/nosql-databases/couchbase-mobile)


подобно @Cris я реализовал класс для синхронизации между клиентом и сервером и решил все известные проблемы до сих пор (отправка/получение данных на/с сервера, слияние конфликтов на основе временных меток, удаление дубликатов записей в ненадежных сетевых условиях, синхронизация вложенных данных и файлов и т. д.. )

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

M3Synchronization * syncEntity = [[M3Synchronization alloc] initForClass: @"Car"
                                                              andContext: context
                                                            andServerUrl: kWebsiteUrl
                                             andServerReceiverScriptName: kServerReceiverScript
                                              andServerFetcherScriptName: kServerFetcherScript
                                                    ansSyncedTableFields:@[@"licenceNumber", @"manufacturer", @"model"]
                                                    andUniqueTableFields:@[@"licenceNumber"]];


syncEntity.delegate = self; // delegate should implement onComplete and onError methods
syncEntity.additionalPostParamsDictionary = ... // add some POST params to authenticate current user

[syncEntity sync];

вы можете найти источник, рабочий пример и многое другое инструкции здесь: github.com/knagode/M3Synchronization.


уведомление пользователя для обновления данных с помощью push-уведомления. Используйте фоновый поток в приложении для проверки локальных данных и данных на облачном сервере, в то время как изменение происходит на сервере,измените локальные данные,наоборот.

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

надеюсь, это может помочь u


Я только что опубликовал первую версию моего нового API синхронизации Core Data Cloud, известного как SynCloud. SynCloud имеет много различий с iCloud, потому что он позволяет использовать многопользовательский интерфейс синхронизации. Он также отличается от других api синхронизации, потому что он позволяет использовать многоплатформенные реляционные данные.

пожалуйста, узнайте больше на http://www.syncloudapi.com

Build с iOS 6 SDK, он очень актуален по состоянию на 27.09.2012.


Я думаю, что хорошим решением проблемы GUID является "распределенная система идентификаторов". Я не уверен, что правильный термин, но я думаю, что это то, что MS SQL server docs использовали для его вызова (SQL использует/использовал этот метод для распределенных/синхронизированных баз данных). Это довольно просто:

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

Я думаю, что это превосходит использование случайных GUID, потому что случайные GUID не на 100% безопасны и обычно должны быть намного длиннее стандартного ID (128-бит против 32-бит). Обычно у вас есть индексы по ID и часто храните ID-номера в памяти, поэтому важно сохранить их небольшими.

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


сначала вы должны переосмыслить, сколько данных, таблиц и отношений у вас будет. В моем решении я реализовал синхронизацию через файлы Dropbox. Я наблюдаю изменения в основном MOC и сохраняю эти данные в файлах (каждая строка сохраняется как gzipped json). Если работает подключение к интернету, я проверяю, есть ли какие-либо изменения в Dropbox (Dropbox дает мне изменения delta), загружаю их и объединяю (последние победы) и, наконец, помещаю измененные файлы. Перед синхронизацией я помещаю файл блокировки в Dropbox, чтобы предотвратить другие клиенты синхронизируют неполные данные. При загрузке изменений безопасно загружать только частичные данные (например, потерянное подключение к интернету). Когда загрузка завершена (полностью или частично), она начинает загружать файлы в основные данные. Когда есть неразрешенные отношения (не все файлы загружаются), он прекращает загрузку файлов и пытается завершить загрузку позже. Отношения хранятся только как GUID, поэтому я могу легко проверить, какие файлы загружать, чтобы иметь полную целостность данных. Синхронизация начинается после изменения ядро данных. Если изменений нет, он проверяет наличие изменений в Dropbox каждые несколько минут и при запуске приложения. Кроме того, когда изменения отправляются на сервер, я отправляю трансляцию на другие устройства, чтобы сообщить им об изменениях, чтобы они могли синхронизировать быстрее. Каждый синхронизированный объект имеет свойство GUID (guid также используется в качестве имени файла для файлов exchange). У меня также есть база данных синхронизации, где я храню версию Dropbox каждого файла (я могу сравнить ее, когда Dropbox delta сбрасывает ее состояние). Файлы также содержат имя сущности, состояние (удалено / не удалено), идентификатор guid (то же, что и имя файла), ревизия базы данных (для обнаружения миграции данных или во избежание синхронизации с версиями приложений never) и, конечно, данные (если строка не удалена).

Это решение работает для тысяч файлов и около 30 организаций. Вместо Dropbox я мог бы использовать key / value store в качестве веб-сервиса REST, который я хочу сделать позже, но у меня нет времени на это :) на данный момент, на мой взгляд, мое решение более надежно, чем iCloud и, что очень важно, что я полностью контролирую его работу (в основном потому, что это мой собственный код).

другое решение-сохранить изменения MOC как транзакции - будет гораздо меньше файлов, обмениваемых с сервером, но сложнее выполнить начальную загрузку в правильном порядке в пустые основные данные. iCloud работает таким образом, а также другие решения синхронизации имеют аналогичный подход, например TICoreDataSync.

-- UPDATE

через некоторое время я перекочевал в ансамбли - Я рекомендую это решение по изобретению колеса.


2017

относительно этого невероятно старого вопроса.

это было бы очень похоже на вопрос

" Я хочу купить устройство, которое является телефоном, который я могу носить с собой , но также использовать для многих вычислительных задач, даже просматривая WWW!"

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

в наши дни создание системы OCC с нуля было бы таким же безумием, как создание базы данных SQL с нуля.

очевидно, что для OCC, который является базовой парадигмой всех нетривиальных приложений, вы используете

  • Firebase
  • PubNub
  • Couchbase

и так далее, которые довольно просто, главный прогресс в человеческой технологии за последние несколько лет.

сегодня, вы не больше создадите OCC с нуля, чем вы

  • написать свою собственную операционную систему с нуля

  • напишите свою собственную базу данных SQL с нуля

  • напишите свой собственный шрифт-отрисовки с нуля

обратите внимание, что действительно, в профессиональном смысле вы больше не можете быть "программистом ios" или "программистом android".

кто заботится о том, как макет таблицы а пуговицы?

вы являетесь экспертом Firebase / whatever, и в качестве случайного побочного вопроса Вы знаете, как кнопки макета и т. д. На ios или android.

единственный вопрос, какие БАДы использовать, например, может PlayFab если это ориентированная игра, может PubNub если это действительно сообщение приводом, может быть, умело.Ио, может быть, данных; kinvey если вы корпоративный - все.