Бөлісу құралы:


CloudKit в Xamarin.iOS

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

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

Внимание

Компания Apple предоставляет инструменты, которые помогают разработчикам надлежащим образом соблюдать Общий регламент по защите данных Европейского союза (GDPR).

Требования

Для выполнения описанных в этой статье действий необходимо выполнить следующие действия.

  • Xcode и пакет SDK для iOS— api Apple Xcode и iOS 8 должны быть установлены и настроены на компьютере разработчика.
  • Visual Studio для Mac — последняя версия Visual Studio для Mac должна быть установлена и настроена на устройстве пользователя.
  • Устройство iOS 8 — устройство iOS под управлением последней версии iOS 8 для тестирования.

Что такое CloudKit?

CloudKit — это способ предоставления разработчикам доступа к серверам iCloud. Она обеспечивает основу как для iCloud Drive, так и для фототеки iCloud. CloudKit поддерживается на устройствах macOS и iOS.

Поддержка CloudKit на устройствах macOS и iOS

CloudKit использует инфраструктуру учетной записи iCloud. Если на устройстве есть пользователь, вошедший в учетную запись iCloud, CloudKit будет использовать свой идентификатор для идентификации пользователя. Если учетная запись недоступна, будет предоставлен ограниченный доступ только для чтения.

CloudKit поддерживает как концепцию общедоступных, так и частных баз данных. Общедоступные базы данных предоставляют "суп" всех данных, к которым у пользователя есть доступ. Частные базы данных предназначены для хранения частных данных, привязанных к конкретному пользователю.

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

Примечание.

Важно отметить, что CloudKit — это транспортная технология. Он не обеспечивает никакой сохраняемости; он позволяет приложению эффективно отправлять и получать информацию от серверов.

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

Включение CloudKit в приложении Xamarin

Прежде чем приложение Xamarin сможет использовать платформу CloudKit, приложение должно быть правильно подготовлено, как описано в руководствах по работе с возможностями и работе с правами.

Чтобы получить доступ к Файлу Accesss.plist, необходимо включить iCloud, хранилище key-value и разрешения CloudKit.

Пример приложения

В примере приложения показано, как использовать CloudKit с Xamarin. Ниже показано, как настроить пример. Для этого требуются дополнительные параметры, кроме того, что требуется только для CloudKit:

  1. Откройте проект в Visual Studio для Mac или Visual Studio.
  2. В Обозреватель решений откройте файл Info.plist и убедитесь, что идентификатор пакета соответствует идентификатору пакета, который был определен в идентификаторе приложения, созданном в рамках настройки подготовки.
  3. Прокрутите вниз до нижней части файла Info.plist и выберите режимы фона, расположение Обновления и удаленные уведомления.
  4. Щелкните правой кнопкой мыши проект iOS в решении и выберите пункт "Параметры".
  5. Выберите подпись пакета iOS, выберите удостоверение разработчика и профиль подготовки, созданный выше.
  6. Убедитесь, что в списке прав.plist включена функция Enable iCloud, хранилище key-value и CloudKit.
  7. Убедитесь, что контейнер Ubiquity существует для приложения. Пример: iCloud.com.your-company.CloudKitAtlas
  8. Сохраните изменения в файле.

С помощью этих параметров пример приложения теперь готов к доступу к API CloudKit Framework, а также к фоновым, расположениям и службам уведомлений.

Обзор API CloudKit

Перед реализацией CloudKit в приложении Xamarin iOS в этой статье рассматриваются основы CloudKit Framework, которые будут включать следующие разделы:

  1. Контейнеры — изолированные оси связи iCloud.
  2. Базы данных — общедоступные и частные доступны для приложения.
  3. Записи — механизм перемещения структурированных данных в CloudKit и из нее.
  4. Зоны записей — это группы записей .
  5. Идентификаторы записей — полностью нормализуются и представляют определенное расположение записи.
  6. Справочник . Предоставление связей между связанными записями в данной базе данных.
  7. Ресурсы — разрешить отправку больших неструктурированных данных в iCloud и связанных с данной записью.

Контейнеры

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

Концепция принятия клиентского приложения и его запуска от других клиентов очень эффективна и обеспечивает следующие преимущества:

  1. Безопасность — одно приложение не может препятствовать другим клиентским приложениям или самой ОС.
  2. Стабильность . Если клиентское приложение завершает работу, оно не может вывести другие приложения ОС.
  3. Конфиденциальность . Каждое клиентское приложение имеет ограниченный доступ к персональным данным, хранящимся на устройстве.

CloudKit был разработан, чтобы обеспечить те же преимущества, что и приведенные выше, и применить их к работе с облачными сведениями:

Приложения CloudKit взаимодействуют с помощью контейнеров

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

Контейнеры предоставляются в CloudKit Framework через CKContainer класс. По умолчанию одно приложение взаимодействует с одним контейнером, и этот контейнер разделяет данные для этого приложения. Это означает, что несколько приложений могут хранить данные в одной учетной записи iCloud, но эти сведения никогда не будут перемешаны.

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

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

Apple предлагает использовать обратную нотацию DNS при создании пространства имен для контейнеров приложений. Пример: iCloud.com.company-name.application-name

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

Базы данных

Одной из основных функций CloudKit является использование модели данных приложения и реплика их моделирование до серверов iCloud. Некоторые сведения предназначены для пользователя, создавшего его, другие сведения — это общедоступные данные, которые могут быть созданы пользователем для общедоступного использования (например, для проверки ресторана), или могут быть сведения о том, что разработчик опубликовал для приложения. В любом случае аудитория не только один пользователь, но и сообщество людей.

Схема контейнеров CloudKit

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

При запуске на устройстве iOS приложение будет иметь доступ только к сведениям для текущего пользователя iCloud. Таким образом, представление приложения контейнера будет следующим образом:

Представление приложений контейнера

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

Базы данных предоставляются в CloudKit Framework через CKDatabase класс. Каждое приложение имеет доступ к двум базам данных: общедоступной базе данных и частной.

Контейнер — это начальная точка входа в CloudKit. Следующий код можно использовать для доступа к общедоступной и частной базе данных из контейнера по умолчанию приложения:

using CloudKit;
//...

public CKDatabase PublicDatabase { get; set; }
public CKDatabase PrivateDatabase { get; set; }
//...

// Get the default public and private databases for
// the application
PublicDatabase = CKContainer.DefaultContainer.PublicCloudDatabase;
PrivateDatabase = CKContainer.DefaultContainer.PrivateCloudDatabase;

Ниже приведены различия между типами баз данных:

Общедоступная база данных Частная база данных
Тип данных Общие данные Данные текущего пользователя
План продаж Учетная запись в квоте разработчика Учетная запись в квоте пользователя
Разрешения по умолчанию Доступный для чтения мир Доступный для чтения пользователей
Редактирование разрешений Роли панели мониторинга iCloud с помощью уровня класса записи Н/П

Записи

Контейнеры хранят базы данных и внутри баз данных — это записи. Записи — это механизм перемещения структурированных данных в CloudKit и из нее:

Контейнеры хранят базы данных и внутри баз данных — записи

Записи предоставляются в CloudKit Framework через CKRecord класс, который упаковывает пары "ключ-значение". Экземпляр объекта в приложении эквивалентен CKRecord объекту в CloudKit. Кроме того, каждый CKRecord имеет тип записи, эквивалентный классу объекта.

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

Класс CKRecord также поддерживает широкий спектр метаданных. Например, запись содержит сведения о том, когда он был создан, и пользователь, создавший его. Запись также содержит сведения о времени последнего изменения и пользователя, изменившего его.

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

Как указано выше, CKRecords пары "ключ-значение" и такие пары данных могут храниться в записи следующими типами:

  1. NSString
  2. NSNumber
  3. NSData
  4. NSDate
  5. CLLocation
  6. CKReferences
  7. CKAssets

Помимо отдельных типов значений запись может содержать однородный массив любого из перечисленных выше типов.

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

using CloudKit;
//...

private const string ReferenceItemRecordName = "ReferenceItems";
//...

var newRecord = new CKRecord (ReferenceItemRecordName);
newRecord ["name"] = (NSString)nameTextField.Text;
await CloudManager.SaveAsync (newRecord);

Зоны записей

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

Группы записей существуют вместе в зоне записей

В заданной зоне записи может быть несколько записей и несколько зон записей в данной базе данных. Каждая база данных содержит зону записей по умолчанию:

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

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

Идентификаторы записей

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

  • Они создаются клиентским приложением.
  • Они полностью нормализуются и представляют конкретное расположение записи.
  • Назначив уникальный идентификатор записи в внешней базе данных имени записи, их можно использовать для моста между локальными базами данных, которые не хранятся в CloudKit.

При создании новых записей разработчики могут выбрать передачу идентификатора записи. Если идентификатор записи не указан, идентификатор UUID будет автоматически создан и назначен записи.

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

Идентификаторы записей предоставляются в CloudKit Framework через CKRecordID класс. Следующий код можно использовать для создания нового идентификатора записи:

var recordID =  new CKRecordID("My Record");

Ссылки

Ссылки предоставляют связи между связанными записями в данной базе данных:

Ссылки предоставляют связи между связанными записями в данной базе данных

В приведенном выше примере родители имеют дочерние дети, чтобы ребенок был дочерним записью родительской записи. Связь переходит от дочерней записи к родительской записи и называется обратной ссылкой.

Ссылки предоставляются в CloudKit Framework через CKReference класс. Это способ позволить серверу iCloud понять связь между записями.

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

Примечание.

Dangling Pointers это возможность при использовании CloudKit. Например, по истечении времени, когда приложение извлекло список указателей записей, выбрали запись, а затем попросили запись, запись может больше не существовать в базе данных. Приложение должно быть закодировано для корректной обработки этой ситуации.

Хотя и не требуется, при работе с CloudKit Framework предпочтительнее использовать обратные ссылки. Apple настроила систему, чтобы сделать этот наиболее эффективный тип ссылок.

При создании ссылки разработчик может предоставить запись, которая уже находится в памяти или создать ссылку на идентификатор записи. Если используется идентификатор записи и указанная ссылка не существует в базе данных, будет создан указатель dangling.

Ниже приведен пример создания ссылки на известную запись:

var reference = new CKReference(newRecord, new CKReferenceAction());

Ресурсы

Ресурсы позволяют отправлять большие неструктурированные данные в iCloud и связаны с данной записью:

Ресурсы позволяют отправлять большие неструктурированные данные в iCloud и связанные с данной записью

На клиенте CKRecord создается файл, описывающий файл, который будет отправлен на сервер iCloud. Создается CKAsset для хранения файла и связан с записью, описывающей ее.

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

Ресурсы предоставляются в CloudKit Framework через CKAsset класс и используются для хранения больших неструктурированных данных. Так как разработчик никогда не хочет иметь большие неструктурированные данные в памяти, ресурсы реализуются с помощью файлов на диске.

Ресурсы принадлежат записям, что позволяет извлекать ресурсы из iCloud с помощью записи в качестве указателя. Таким образом, сервер может собирать ресурсы мусора при удалении записи, владеющей ресурсом.

Так как CKAssets предназначены для обработки больших файлов данных, Apple разработал CloudKit для эффективной отправки и скачивания ресурсов.

Следующий код можно использовать для создания ресурса и связывания его с записью:

var fileUrl = new NSUrl("LargeFile.mov");
var asset = new CKAsset(fileUrl);
newRecord ["name"] = asset;

Теперь мы рассмотрели все основные объекты в CloudKit. Контейнеры связаны с приложениями и содержат базы данных. Базы данных содержат записи, сгруппированные в зоны записей и указывающие на идентификаторы записей. Связи "Родительский-дочерний" определяются между записями с помощью ссылок. Наконец, большие файлы можно отправлять и связывать с записями с помощью ресурсов.

API удобства CloudKit

Apple предлагает два различных набора API для работы с CloudKit:

  • Операционный API — предлагает каждую функцию CloudKit. Для более сложных приложений этот API обеспечивает подробный контроль над CloudKit.
  • Удобный API— предлагает общее предварительно настроенное подмножество функций CloudKit. Он предоставляет удобное и простое решение для включения функций CloudKit в приложение iOS.

Удобный API обычно является лучшим выбором для большинства приложений iOS, и Apple предлагает начать с него. В остальной части этого раздела рассматриваются следующие разделы API удобства.

  • Сохранение записи.
  • Получение записи.
  • Обновление записи.

Распространенный код установки

Прежде чем приступить к работе с API удобства CloudKit, требуется стандартный код установки. Начните с изменения файла приложения AppDelegate.cs и сделайте его следующим образом:

using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
using CloudKit;

namespace CloudKitAtlas
{
    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        public override UIWindow Window { get; set;}
        public CKDatabase PublicDatabase { get; set; }
        public CKDatabase PrivateDatabase { get; set; }

        public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
        {
            application.RegisterForRemoteNotifications ();

            // Get the default public and private databases for
            // the application
            PublicDatabase = CKContainer.DefaultContainer.PublicCloudDatabase;
            PrivateDatabase = CKContainer.DefaultContainer.PrivateCloudDatabase;

            return true;
        }

        public override void RegisteredForRemoteNotifications (UIApplication application, NSData deviceToken)
        {
            Console.WriteLine ("Registered for Push notifications with token: {0}", deviceToken);
        }

        public override void FailedToRegisterForRemoteNotifications (UIApplication application, NSError error)
        {
            Console.WriteLine ("Push subscription failed");
        }

        public override void ReceivedRemoteNotification (UIApplication application, NSDictionary userInfo)
        {
            Console.WriteLine ("Push received");
        }
    }
}

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

Затем добавьте следующий код в любой контейнер представления или представления, который будет использовать CloudKit:

using CloudKit;
//...

public AppDelegate ThisApp {
    get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
}

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

С помощью этого кода давайте рассмотрим реализацию API CloudKit Для удобства в приложении Xamarin iOS 8.

Сохранение записи

Используя приведенный выше шаблон при обсуждении записей, следующий код создаст новую запись и использует API удобства для сохранения его в общедоступной базе данных:

private const string ReferenceItemRecordName = "ReferenceItems";
...

// Create a new record
var newRecord = new CKRecord (ReferenceItemRecordName);
newRecord ["name"] = (NSString)nameTextField.Text;

// Save it to the database
ThisApp.PublicDatabase.SaveRecord(newRecord, (record, err) => {
    // Was there an error?
    if (err != null) {
        ...
    }
});

Три вещи, которые следует отметить о приведенном выше коде:

  1. Вызывая SaveRecord метод, PublicDatabaseразработчику не нужно указывать способ отправки данных, то, в какой зоне она записывается и т. д. API удобства заботится обо всех этих деталях.
  2. Вызов является асинхронным и предоставляет подпрограмму обратного вызова при завершении вызова с успехом или сбоем. Если вызов завершается сбоем, будет предоставлено сообщение об ошибке.
  3. CloudKit не предоставляет локальное хранилище и сохраняемость; это только носитель передачи. Таким образом, когда запрос выполняется для сохранения записи, он немедленно отправляется на серверы iCloud.

Примечание.

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

Получение записи

С помощью записи, созданной и успешно хранящейся на сервере iCloud, используйте следующий код для получения записи:

// Create a record ID and fetch the record from the database
var recordID = new CKRecordID("MyRecordName");
ThisApp.PublicDatabase.FetchRecord(recordID, (record, err) => {
    // Was there an error?
    if (err != null) {
        ...
    }
});

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

Обновление записи

После получения записи с серверов iCloud можно использовать следующий код для изменения записи и сохранения изменений обратно в базу данных:

// Create a record ID and fetch the record from the database
var recordID = new CKRecordID("MyRecordName");
ThisApp.PublicDatabase.FetchRecord(recordID, (record, err) => {
    // Was there an error?
    if (err != null) {

    } else {
        // Modify the record
        record["name"] = (NSString)"New Name";

        // Save changes to database
        ThisApp.PublicDatabase.SaveRecord(record, (r, e) => {
            // Was there an error?
            if (e != null) {
                 ...
            }
        });
    }
});

Метод FetchRecord возвращаемого CKRecord значенияPublicDatabase, если вызов выполнен успешно. Затем приложение изменяет запись и снова вызывает SaveRecord запись, чтобы записать изменения обратно в базу данных.

В этом разделе показан типичный цикл, используемый приложением при работе с API удобства CloudKit. Приложение сохранит записи в iCloud, получите эти записи из iCloud, измените записи и сохраните эти изменения обратно в iCloud.

Проектирование для масштабируемости

До сих пор эта статья рассмотрела хранение и получение всей объектной модели приложения с серверов iCloud, каждый раз, когда она будет работать. Хотя этот подход хорошо работает с небольшим объемом данных и очень небольшой пользовательской базой, он не хорошо масштабируется при увеличении объема информации и (или) базы пользователей.

Большие данные, крошечное устройство

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

  • Сохранение больших данных в Cloud — CloudKit было разработано для эффективной обработки больших данных.
  • Клиент должен просматривать только срез этих данных. Сведите минимальное количество данных , необходимых для обработки любой задачи в определенное время.
  • Клиентские представления могут изменяться . Так как каждый пользователь имеет разные предпочтения, срез отображаемых данных может изменяться от пользователя к пользователю, а индивидуальное представление пользователя любого заданного среза может отличаться.
  • Клиент использует запросы для фокусировки точки представления. Запросы позволяют пользователю просматривать небольшое подмножество большего набора данных, существующего в облаке.

Запросы

Как указано выше, запросы позволяют разработчику выбрать небольшое подмножество большого набора данных, существующего в облаке. Запросы предоставляются в CloudKit Framework через CKQuery класс.

Запрос объединяет три разных элемента: тип записи ( RecordType), предикат ( NSPredicate) и, при необходимости, дескриптор сортировки ( NSSortDescriptors). CloudKit поддерживает большую NSPredicateчасть.

Поддерживаемые предикаты

CloudKit поддерживает следующие типы NSPredicates при работе с запросами:

  1. Совпадающие записи, в которых имя равно значению, хранящееся в переменной:

    NSPredicate.FromFormat(string.Format("name = '{0}'", recordName))
    
  2. Позволяет соответствовать динамическому значению ключа, чтобы ключ не был известен во время компиляции:

    NSPredicate.FromFormat(string.Format("{0} = '{1}'", key, value))
    
  3. Сопоставления записей, в которых значение записи больше заданного значения:

    NSPredicate.FromFormat(string.Format("start > {0}", (NSDate)date))
    
  4. Соответствующие записи, в которых расположение записи находится в пределах 100 метров от заданного расположения:

    var location = new CLLocation(37.783,-122.404);
    var predicate = NSPredicate.FromFormat(string.Format("distanceToLocation:fromLocation(Location,{0}) < 100", location));
    
  5. CloudKit поддерживает маркеризованный поиск. Этот вызов создаст два маркера, один для after одного и другого.session Он вернет запись, содержащую эти два маркера:

    NSPredicate.FromFormat(string.Format("ALL tokenize({0}, 'Cdl') IN allTokens", "after session"))
    
  6. CloudKit поддерживает составные предикаты, присоединенные с помощью AND оператора.

    NSPredicate.FromFormat(string.Format("start > {0} AND name = '{1}'", (NSDate)date, recordName))
    

Создание запросов

Следующий код можно использовать для создания CKQuery в приложении Xamarin iOS 8:

var recordName = "MyRec";
var predicate = NSPredicate.FromFormat(string.Format("name = '{0}'", recordName));
var query = new CKQuery("CloudRecords", predicate);

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

Выполнение запроса

После создания запроса используйте следующий код для выполнения запроса и обработки возвращаемых записей:

var recordName = "MyRec";
var predicate = NSPredicate.FromFormat(string.Format("name = {0}", recordName));
var query = new CKQuery("CloudRecords", predicate);

ThisApp.PublicDatabase.PerformQuery(query, CKRecordZone.DefaultRecordZone().ZoneId, (NSArray results, NSError err) => {
    // Was there an error?
    if (err != null) {
       ...
    } else {
        // Process the returned records
        for(nint i = 0; i < results.Count; ++i) {
            var record = (CKRecord)results[i];
        }
    }
});

Приведенный выше код принимает созданный выше запрос и выполняет его в общедоступной базе данных. Так как зона записи не указана, все зоны выполняются поиск. Если ошибки не произошли, массив CKRecords возвращается в соответствии с параметрами запроса.

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

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

Подписки

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

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

Подписки предоставляются в CloudKit Framework через CKSubscription класс. Они объединяют тип записи ( RecordType), предикат ( NSPredicate) и push-уведомление Apple ( Push).

Примечание.

Push-уведомления CloudKit немного дополнены, так как они содержат полезные данные, содержащие конкретные сведения CloudKit, такие как то, что вызвало отправку.

Как работают подписки

Прежде чем реализовать подписку в коде C#, давайте рассмотрим, как работают подписки:

Обзор работы подписок

На приведенном выше графике показан типичный процесс подписки следующим образом:

  1. Клиентское устройство создает новую подписку, содержащую набор условий, которые активируют подписку и push-уведомление, которое будет отправляться при возникновении триггера.
  2. Подписка отправляется в базу данных, в которой она добавляется в коллекцию существующих подписок.
  3. На втором устройстве создается новая запись и сохраняется в базе данных.
  4. База данных выполняет поиск по списку подписок, чтобы узнать, соответствует ли новая запись условиям.
  5. Если совпадение найдено, push-уведомление отправляется на устройство, которое зарегистрировало подписку со сведениями о записи, которая вызвала его активацию.

С помощью этих знаний давайте рассмотрим создание подписок в приложении Xamarin iOS 8.

Создание подписок

Следующий код можно использовать для создания подписки:

// Create a new subscription
DateTime date;
var predicate = NSPredicate.FromFormat(string.Format("start > {0}", (NSDate)date));
var subscription = new CKSubscription("RecordType", predicate, CKSubscriptionOptions.FiresOnRecordCreation);

// Describe the type of notification
var notificationInfo = new CKNotificationInfo();
notificationInfo.AlertLocalizationKey = "LOCAL_NOTIFICATION_KEY";
notificationInfo.SoundName = "ping.aiff";
notificationInfo.ShouldBadge = true;

// Attach the notification info to the subscription
subscription.NotificationInfo = notificationInfo;

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

Сохранение подписок

С помощью созданной подписки следующий код сохранит его в базе данных:

// Save the subscription to the database
ThisApp.PublicDatabase.SaveSubscription(subscription, (s, err) => {
    // Was there an error?
    if (err != null) {

    }
});

Используя API удобства, вызов является асинхронным, простым и обеспечивает простую обработку ошибок.

Обработка push-уведомлений

Если разработчик ранее использовал push-уведомления Apple (APS), то процесс работы с уведомлениями, созданными CloudKit, должен быть знаком.

В файле AppDelegate.csпереопределите ReceivedRemoteNotification класс следующим образом:

public override void ReceivedRemoteNotification (UIApplication application, NSDictionary userInfo)
{
    // Parse the notification into a CloudKit Notification
    var notification = CKNotification.FromRemoteNotificationDictionary (userInfo);

    // Get the body of the message
    var alertBody = notification.AlertBody;

    // Was this a query?
    if (notification.NotificationType == CKNotificationType.Query) {
        // Yes, convert to a query notification and get the record ID
        var query = notification as CKQueryNotification;
        var recordID = query.RecordId;
    }
}

Приведенный выше код просит CloudKit проанализировать userInfo в cloudKit Notification. Далее извлекается информация об оповещении. Наконец, проверяется тип уведомления, и уведомление обрабатывается соответствующим образом.

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

Учетные записи пользователей CloudKit

Как отмечалось в начале этой статьи, CloudKit построен на основе существующей инфраструктуры iCloud. В следующем разделе подробно описано, как учетные записи предоставляются разработчику с помощью API CloudKit.

Проверка подлинности

При работе с учетными записями пользователей сначала следует учитывать проверку подлинности. CloudKit поддерживает проверку подлинности с помощью пользователя iCloud, вошедшего в систему на устройстве. Проверка подлинности выполняется за кулисами и обрабатывается iOS. Таким образом, разработчикам никогда не придется беспокоиться о реализации проверки подлинности. Они тестируют только, если пользователь вошел в систему.

Сведения об учетной записи пользователя

CloudKit предоставляет следующие сведения о пользователе для разработчика:

  • Удостоверение — способ уникальной идентификации пользователя.
  • Метаданные — возможность сохранения и получения сведений о пользователях.
  • Конфиденциальность — все сведения обрабатываются в сознательных поместьях конфиденциальности. Ничего не предоставляется, если пользователь не согласился с ним.
  • Обнаружение — дает пользователям возможность обнаруживать своих друзей, использующих одно и то же приложение.

Далее мы подробно рассмотрим эти темы.

Идентификация

Как описано выше, CloudKit позволяет приложению однозначно идентифицировать данного пользователя:

Уникально идентифицируется заданный пользователь

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

Так как это происходит из iCloud, существует богатое резервное хранилище сведений о пользователях. И поскольку iCloud на самом деле размещает контейнер, он может сопоставить пользователей. На приведенном выше рисунке пользователь, чья учетная запись user@icloud.com iCloud связана с текущим клиентом.

В контейнере по контейнерам создается уникальный случайный идентификатор пользователя и связан с учетной записью iCloud пользователя (адрес электронной почты). Этот идентификатор пользователя возвращается в приложение и может использоваться в любом случае разработчику.

Примечание.

Разные приложения, работающие на одном устройстве для одного пользователя iCloud, будут иметь разные идентификаторы пользователей, так как они подключены к разным контейнерам CloudKit.

Следующий код получает идентификатор пользователя CloudKit для текущего вошедшего в систему пользователя iCloud на устройстве:

public CKRecordID UserID { get; set; }
...

// Get the CloudKit User ID
CKContainer.DefaultContainer.FetchUserRecordId ((recordID, err) => {
    // Was there an error?
    if (err!=null) {
        Console.WriteLine("Error: {0}", err.LocalizedDescription);
    } else {
        // Save user ID
        UserID = recordID;
    }
});

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

Метаданные

Каждый пользователь в CloudKit имеет определенные метаданные, описывающие их. Эти метаданные представлены в виде записи CloudKit:

Каждый пользователь в CloudKit имеет определенные метаданные, описывающие их

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

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

Используйте следующий код для доступа к записи пользователя:

public CKRecord UserRecord { get; set; }
...

// Get the user's record
PublicDatabase.FetchRecord(UserID, (record ,er) => {
    //was there an error?
    if (er != null) {
        Console.WriteLine("Error: {0}", er.LocalizedDescription);
    } else {
        // Save the user record
        UserRecord = record;
    }
});

Приведенный выше код запрашивает общедоступную базу данных, чтобы вернуть запись пользователя, к которому мы доступили выше. Так как эта информация поступает с сервера iCloud, вызов является асинхронным и требуется обработка ошибок.

Конфиденциальность

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

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

Обнаружение

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

Пользователь может обнаруживать других пользователей приложения.

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

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

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

Чтобы вернуться, существует три различных типа входных данных, доступных для обнаружения пользователей:

  • Идентификатор записи пользователя — обнаружение можно выполнить с идентификатором пользователя, зарегистрированного в cloudKit.
  • Адрес электронной почты пользователя — пользователь может указать адрес электронной почты и его можно использовать для обнаружения.
  • Контактная книга — адресная книга пользователя может использоваться для обнаружения пользователей приложения с тем же адресом электронной почты, что и в контактах.

Обнаружение пользователей вернет следующие сведения:

  • Идентификатор записи пользователя — уникальный идентификатор пользователя в общедоступной базе данных.
  • Имя и фамилия — как хранится в общедоступной базе данных.

Эти сведения будут возвращены только для пользователей, которые выбрали обнаружение.

Следующий код обнаружит сведения о пользователе, вошедшего в iCloud на устройстве:

public CKDiscoveredUserInfo UserInfo { get; set; }
//...

// Get the user's metadata
CKContainer.DefaultContainer.DiscoverUserInfo(UserID, (info, e) => {
    // Was there an error?
    if (e != null) {
        Console.WriteLine("Error: {0}", e.LocalizedDescription);
    } else {
        // Save the user info
        UserInfo = info;
    }
});

Используйте следующий код для запроса всех пользователей в книге контактов:

// Ask CloudKit for all of the user's friends information
CKContainer.DefaultContainer.DiscoverAllContactUserInfos((info, er) => {
    // Was there an error
    if (er != null) {
        Console.WriteLine("Error: {0}", er.LocalizedDescription);
    } else {
        // Process all returned records
        for(int i = 0; i < info.Count(); ++i) {
            // Grab a user
            var userInfo = info[i];
        }
    }
});

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

Среды разработки и рабочей среды

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

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

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

Примечание.

Симулятор iOS работает только с средой разработки. Когда разработчик готов протестировать приложение в рабочей среде, требуется физическое устройство iOS.

Доставка приложения с поддержкой CloudKit

Перед доставкой приложения, использующего CloudKit, необходимо настроить для целевого объекта Production CloudKit Environment или приложение будет отклонено Apple.

Выполните следующие действия.

  1. В Visual Studio для Ma скомпилируйте приложение для устройства iOS выпуска>:

    Компиляция приложения для выпуска

  2. В меню "Сборка " выберите "Архив":

    Выбор архива

  3. Архив будет создан и отображен в Visual Studio для Mac:

    Архив будет создан и отображен

  4. Запустите Xcode.

  5. В меню "Окно" выберите Организатор:

    Выбор организатора

  6. Выберите архив приложения и нажмите кнопку "Экспорт...

    Архив приложения

  7. Выберите метод для экспорта и нажмите кнопку "Далее ":

    Выбор метода для экспорта

  8. Выберите команду разработчиков из раскрывающегося списка и нажмите кнопку "Выбрать":

    Выберите команду разработчиков из раскрывающегося списка

  9. Выберите рабочую среду из раскрывающегося списка и нажмите кнопку "Далее":

    Выберите рабочую среду из раскрывающегося списка

  10. Просмотрите параметр и нажмите кнопку "Экспорт ":

    Просмотр параметра

  11. Выберите расположение для создания результирующего файла приложения .ipa .

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

Когда следует использовать CloudKit

Как мы видели в этой статье, CloudKit предоставляет простой способ хранения и получения информации с серверов iCloud. Это означает, что CloudKit не устарел или не рекомендует любые существующие средства или платформы.

Случаи использования

Следующие варианты использования помогут разработчику решить, когда следует использовать определенную платформу или технологию iCloud:

  • Хранилище ключей и значений iCloud — асинхронно сохраняет небольшое количество данных в актуальном состоянии и отлично подходит для работы с предпочтениями приложения. Однако оно ограничено для очень небольшого объема информации.
  • ICloud Drive — построен на основе существующих API документов iCloud и предоставляет простой API для синхронизации неструктурированных данных из файловой системы. Он предоставляет полный автономный кэш в Mac OS X и отлично подходит для приложений, ориентированных на документ.
  • ICloud Core Data — позволяет реплика данных между всеми устройствами пользователя. Данные являются одним пользователем и отлично подходит для хранения закрытых структурированных данных в синхронизации.
  • CloudKit — предоставляет общедоступные данные как структуры, так и массовые, и может обрабатывать как большой набор данных, так и большие неструктурированные файлы. Она привязана к учетной записи iCloud пользователя и предоставляет клиенту перенаправленную передачу данных.

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

Итоги

В этой статье описано краткое введение в API CloudKit. В нем показано, как подготовить и настроить приложение Xamarin iOS для использования CloudKit. Он рассмотрел функции API удобства CloudKit. В нем показано, как разработать приложение с поддержкой CloudKit для масштабируемости с помощью запросов и подписок. И, наконец, он отображает сведения о учетной записи пользователя, которые предоставляются приложению CloudKit.