Варианты хранения для автономного и онлайн-приложения iOS с синхронизацией - PullRequest
0 голосов
/ 09 мая 2020

Давайте рассмотрим этот пример использования, приложение iOS для рецептов:

  • Publi c данные (общие для всех пользователей, только чтение, загрузка по запросу): Когда пользователь сначала открывает приложение, он находит неглубокий список (не полностью загруженных) 10 рецептов (полученных с удаленного сервера) с возможностью загрузки полного рецепта, а затем он может открыть экран деталей рецепта. И в любой момент список может увеличиваться, и у пользователя всегда должны быть самые свежие данные (получение с удаленного компьютера и синхронизация c). Эти данные должны быть доступны в автономном режиме и должны извлекать новый контент при подключении к Интернету. (Только чтение)

  • Частные данные (указывается c для пользователя): пользователь может создать собственный рецепт, который хранится локально и синхронизируется удаленно. Эти данные должны быть доступны в автономном режиме и должны синхронизироваться при подключении к сети (чтение и запись)

  • Данные должны синхронизироваться на всех iOS устройствах

Я рассматриваю возможность использования Core Data (в автономном режиме) и CloudKit (удаленно). Но я не уверен, справится ли это с описанным выше сценарием или есть какие-то ограничения. Как вы думаете, Core Data (в автономном режиме) и CloudKit - лучший вариант? какие-то ограничения? какие еще варианты вы порекомендуете

1 Ответ

2 голосов
/ 13 мая 2020

Архитектура, которую вы описали в своем вопросе, хорошо работает с Core Data и CloudKit. Могут быть и другие варианты (например, Firebase, Realm), которые стоит изучить, но, поскольку вы упомянули фреймворки Apple, я ограничусь только ими. Это все из моего собственного опыта, , поэтому ваш пробег может отличаться .

Давайте начнем с упрощенного ответа.

Apple предлагает NSPersistentCloudKitContainer, который инкапсулирует стек Core Data и отражает постоянное хранилище в частной базе данных CloudKit. Хотя это отличное решение для новых приложений, его нельзя использовать с существующими контейнерами CloudKit. «Core Data владеет схемой CloudKita, созданной из модели Core Data. Существующие контейнеры CloudKit несовместимы с этой схемой». Но это все еще может быть путь, который стоит изучить, и есть много доступных ресурсов:

Теперь, разобравшись с этим, давайте углубимся в некоторые особенности.

До NSPersistentCloudKitContainer приложения должны были управлять синхронизацией и хранилищем между Core Data и CloudKit фреймворков. Хотя это может показаться непосильной задачей, с ней можно справиться. При приближении к решению необходимо иметь в виду несколько вещей:

  • Лучше всего рассматривать ваши хранилища CloudKit как источник истины .

  • Важно поддерживать уникальный идентификатор между записью Core Data и записью CloudKit.

  • В первую очередь ваше приложение / пользовательский интерфейс должны управляться из хранилища Core Data .

  • Обработка задач - например, создание рецептов, сохранение рецептов, обновление рецептов - поскольку Operation s может быть полезным.

CloudKit

Открытый / частный / общий доступ - это основа функционирования CloudKit. Контейнер CloudKit имеет три базы данных (CKDatabase):

  • privateCloudDatabase : для чтения владельцем, доступ для записи владельцем. Не отображается для вас через Портал разработчика.

  • publicCloudDatabase : доступно для чтения всем, доступно для записи владельцем. Может быть заблокирован по ролям и виден вам через портал разработчика.

  • sharedCloudDatabase : доступно для участников общего доступа (CKShare), но не видны вам.

Эта структура хорошо согласуется с вашим желанием разделить публикуемые c и личные / пользовательские данные.

Подписки (CKSubscription) можно настроить в базах данных, чтобы уведомлять вас о произошедших изменениях. На этом этапе ваше приложение может получать записи с изменениями. Вы можете указать токен изменения (CKServerChangeToken), чтобы ограничить результаты запроса только теми записями, которые изменились с момента последней загрузки. У каждого устройства есть собственная подписка и токен, поэтому оно будет загружать только те данные и записывать необходимые изменения. Таким образом, CloudKit является источником истины , и все изменения - независимо от того, где они происходят - отражаются на других устройствах.

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

Вы можете создать подписку как для «publi c», так и для «частных» баз данных, чтобы гарантировать возможность отслеживания изменений для обеих.

CloudKit и схемы основных данных

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

Core Data рекомендует, чтобы все отношения были двунаправленными. Например: A Recipe будет иметь отношение к своим Ingredient s (один ко многим), И Ingredient будет иметь отношение к его Recipe (один к одному).

In CloudKit, рекомендуются только однонаправленные отношения с использованием CKReference. Таким образом, для данного примера Recipe не будет иметь прямой ссылки на ингредиенты, но Ingredient будет иметь ссылку на связь с Recipe, который его использует.

Как часть взаимодействия между Core Data и CloudKit, вам понадобится уникальный идентификатор, который можно запрашивать в обеих средах. Обычный способ добиться этого - использовать UUID. CKRecord.ID состоит из «recordName» (String) и «zoneID» (CKRecordZone.ID). Использование UUID.uuidString в качестве 'recordName' создаст уникальные записи в CloudKit, но также даст вам последовательную ссылку на сущности в Core Data.

Core Data

Как вы указали, автономный доступ к данным имеет решающее значение для удобства использования вашего приложения. Core Data - отличный вариант здесь. Даже если у вас есть возможность отображать результаты непосредственно из CKQuery, сохранение этих данных имеет некоторые преимущества. Я рассматриваю локальное хранилище Core Data как интерфейс для всех данных в моем приложении. Это означает, что для моих пользовательских данных существует единый интерфейс.

Любое изменение, которое вносится в локальные данные, также отправляется в CloudKit, а любая запись, поступающая из CloudKit, добавляется или изменяется в локальных Core Data store.

Использование Core Data таким образом позволяет вам воспользоваться такими инструментами, как NSFetchedResultsController, которые можно использовать для автоматического отражения изменений, внесенных в набор сущностей.

Кроме того, вы могут подключаться к Notification NSManagedObjectContextDidSave, помогают поддерживать пользовательский интерфейс ваших приложений в актуальном состоянии, когда изменения объединяются из взаимодействий CloudKit.

Помните, что попытка выполнения сложных задач с использованием NSPersistentContainer.viewContext может привести к проблемы с производительностью, поэтому вы захотите ознакомиться с DispatchQueue s.

Operations

Взаимодействие с CloudKit основано на операциях. Запросы и записи определены как подклассы Operation. Каждая задача определяется и затем добавляется в очередь для обработки. Эти операции выполняются асинхронно. Я считаю полезным распространить этот стиль программирования на другие области вашего приложения.

Например: когда я создаю новый Recipe, это Operation против Core Data, а затем у меня Operation для создания этой записи в CloudKit. Вторая операция зависит от первой и отменяется, если первая не удалась.

Становится немного легче думать о координации между Core Data и CloudKit как о серии задач, которые необходимо выполнить. . Уведомление об изменении доставляется в ваше приложение> Получить изменения (используя токен изменения)> Добавить / обновить эти записи в Core Data> Обновить пользовательский интерфейс (автоматически / вручную). Каждый из них является звеном в цепочке и зависит от последнего, которое должно быть завершено перед тем, как двигаться дальше. помочь с этим процессом.

В целом Core Data и CloudKit хорошо интегрируются друг с другом и обычно используются для того типа сценария, который вы пытаетесь реализовать. В зависимости от сложности или степени разработки, на которой вы находитесь, NSPersistentCloudKitContainer может быть хорошей отправной точкой. Но как только вы выйдете за рамки его возможностей, вам захочется узнать о проблемах и функциях, указанных выше.

...