CloudKit dans Xamarin.iOS

L’infrastructure CloudKit simplifie le développement d’applications qui accèdent à iCloud. Cela inclut la récupération des données d’application et des droits relatifs aux ressources, ainsi que la possibilité de stocker en toute sécurité les informations d’application. Ce kit offre aux utilisateurs une couche d’anonymat en autorisant l’accès aux applications avec leurs ID iCloud sans partager d’informations personnelles.

Les développeurs peuvent se concentrer sur leurs applications côté client et laisser iCloud éliminer la nécessité d’écrire une logique d’application côté serveur. CloudKit fournit une authentification, des bases de données privées et publiques, ainsi que des services de stockage de données et de ressources structurés.

Important

Apple fournit des outils pour aider les développeurs à gérer correctement le Règlement général sur la protection des données (RGPD) de l’Union européenne.

Spécifications

Les éléments suivants sont nécessaires pour effectuer les étapes présentées dans cet article :

  • Xcode et le KIT de développement logiciel (SDK) iOS : les API Xcode et iOS 8 d’Apple doivent être installées et configurées sur l’ordinateur du développeur.
  • Visual Studio pour Mac : la dernière version de Visual Studio pour Mac doit être installée et configurée sur l’appareil utilisateur.
  • Appareil iOS 8 : appareil iOS exécutant la dernière version d’iOS 8 à des fins de test.

Qu’est-ce que CloudKit ?

CloudKit est un moyen de donner au développeur l’accès aux serveurs iCloud. Il fournit la base d’iCloud Drive et de la photothèque iCloud. CloudKit est pris en charge sur les appareils macOS et iOS.

Prise en charge de CloudKit sur les appareils macOS et iOS

CloudKit utilise l’infrastructure de compte iCloud. Si un utilisateur s’est connecté à un compte iCloud sur l’appareil, CloudKit utilise son ID pour identifier l’utilisateur. Si aucun compte n’est disponible, un accès en lecture seule limité sera fourni.

CloudKit prend en charge à la fois le concept de bases de données publiques et privées. Les bases de données publiques fournissent une « soupe » de toutes les données auxquelles l’utilisateur a accès. Les bases de données privées sont destinées à stocker les données privées liées à un utilisateur spécifique.

CloudKit prend en charge les données structurées et en bloc. Il est capable de gérer les transferts de fichiers volumineux en toute transparence. CloudKit s’occupe de transférer efficacement des fichiers volumineux vers et depuis les serveurs iCloud en arrière-plan, ce qui permet au développeur de se concentrer sur d’autres tâches.

Notes

Il est important de noter que CloudKit est une technologie de transport. Il ne fournit aucune persistance; elle permet uniquement à une application d’envoyer et de recevoir efficacement des informations à partir des serveurs.

Au jour où nous écrivons ces lignes, Apple fournit initialement gratuitement CloudKit avec une limite élevée de bande passante et de capacité de stockage. Pour les projets plus grands ou les applications avec une grande base d’utilisateurs, Apple a laissé entendre qu’une échelle tarifaire abordable sera fournie.

Activation de CloudKit dans une application Xamarin

Pour qu’une application Xamarin puisse utiliser l’infrastructure CloudKit, l’application doit être correctement provisionnée, comme indiqué dans les guides Utilisation des fonctionnalités et Utilisation des droits d’utilisation .

Pour accéder à CloudKit, le fichier Entitlements.plist doit inclure Activer iCloud, stockage clé-valeur et autorisations CloudKit .

Exemple d'application

L’exemple CloudKitAtlas montre comment utiliser CloudKit avec Xamarin. Les étapes ci-dessous montrent comment configurer l’exemple : il nécessite des paramètres supplémentaires au-delà de ce qui est requis pour CloudKit seul :

  1. Ouvrez le projet dans Visual Studio pour Mac ou Visual Studio.
  2. Dans le Explorateur de solutions, ouvrez le fichier Info.plist et vérifiez que l’identificateur de bundle correspond à celui qui a été défini dans ID d’application créé dans le cadre de la configuration d’approvisionnement.
  3. Faites défiler jusqu’au bas du fichier Info.plist et sélectionnez Modes d’arrière-plan activés, Emplacement Mises à jour et Notifications à distance.
  4. Cliquez avec le bouton droit sur le projet iOS dans la solution, puis sélectionnez Options.
  5. Sélectionnez Signature de bundle iOS, sélectionnez l’identité du développeur et le profil d’approvisionnement créés ci-dessus.
  6. Assurez-vous que la liste Entitlements.plist inclut Activer iCloud, le stockage clé-valeur et CloudKit.
  7. Vérifiez que le conteneur Ubiquity existe pour l’application. Exemple : iCloud.com.your-company.CloudKitAtlas
  8. Enregistrez les modifications du fichier.

Une fois ces paramètres en place, l’exemple d’application est maintenant prêt à accéder aux API CloudKit Framework ainsi qu’aux services d’arrière-plan, d’emplacement et de notification.

Vue d’ensemble de l’API CloudKit

Avant d’implémenter CloudKit dans une application iOS Xamarin, cet article va aborder les principes de base de CloudKit Framework, qui comprend les rubriques suivantes :

  1. Conteneurs : silos isolés de communications iCloud.
  2. Bases de données : les bases de données publiques et privées sont disponibles pour l’application.
  3. Enregistrements : mécanisme dans lequel les données structurées sont déplacées vers et à partir de CloudKit.
  4. Zones d’enregistrement : groupes d’enregistrements.
  5. Identificateurs d’enregistrement : sont entièrement normalisés et représentent l’emplacement spécifique de l’enregistrement.
  6. Référence : fournissez des relations parent-enfant entre les enregistrements associés dans une base de données donnée.
  7. Ressources : autorise le chargement d’un fichier de données volumineuses et non structurées sur iCloud et leur association à un enregistrement donné.

Containers

Une application donnée s’exécutant sur un appareil iOS s’exécute toujours avec d’autres applications et services sur cet appareil. Sur l’appareil client, l’application va être cloisonnée ou bac à sable d’une manière ou d’une autre. Dans certains cas, il s’agit d’un bac à sable littéral, et dans d’autres, l’application s’exécute simplement dans son propre espace mémoire.

Le concept de prendre une application cliente et de l’exécuter séparément des autres clients est très puissant et offre les avantages suivants :

  1. Sécurité : une application ne peut pas interférer avec d’autres applications clientes ou le système d’exploitation lui-même.
  2. Stabilité : si l’application cliente se bloque, elle ne peut pas retirer d’autres applications du système d’exploitation.
  3. Confidentialité : chaque application cliente a un accès limité aux informations personnelles stockées dans l’appareil.

CloudKit a été conçu pour offrir les mêmes avantages que ceux répertoriés ci-dessus et les appliquer à l’utilisation d’informations basées sur le cloud :

Les applications CloudKit communiquent à l’aide de conteneurs

Tout comme l’application étant l’une des nombreuses en cours d’exécution sur l’appareil, les communications de l’application avec iCloud sont une des nombreuses. Chacun de ces différents silos de communication est appelé Conteneurs.

Les conteneurs sont exposés dans CloudKit Framework via la CKContainer classe . Par défaut, une application communique avec un conteneur et ce conteneur sépare les données de cette application. Cela signifie que plusieurs applications peuvent stocker des informations dans le même compte iCloud, mais ces informations ne seront jamais entremêlées.

La conteneurisation des données iCloud permet également à CloudKit d’encapsuler les informations utilisateur. De cette façon, l’application aura un accès limité au compte iCloud et aux informations utilisateur stockées dans, tout en protégeant la confidentialité et la sécurité de l’utilisateur.

Les conteneurs sont entièrement gérés par le développeur de l’application via le portail WWDR. L’espace de noms du conteneur étant global pour tous les développeurs Apple, le conteneur doit non seulement être unique aux applications d’un développeur donné, mais à tous les développeurs et applications Apple.

Apple suggère d’utiliser la notation DNS inversée lors de la création de l’espace de noms pour les conteneurs d’application. Exemple : iCloud.com.company-name.application-name

Bien que les conteneurs soient, par défaut, liés un à un à une application donnée, ils peuvent être partagés entre les applications. Ainsi, plusieurs applications peuvent se coordonner sur un seul conteneur. Une seule application peut également communiquer avec plusieurs conteneurs.

Bases de données

L’une des principales fonctions de CloudKit consiste à prendre le modèle de données d’une application et la réplication de ce modèle sur les serveurs iCloud. Certaines informations sont destinées à l’utilisateur qui les a créées, d’autres sont des données publiques qui peuvent être créées par un utilisateur pour un usage public (comme une révision de restaurant), ou il peut s’agir d’informations que le développeur a publiées pour l’application. Dans les deux cas, le public n’est pas qu’un seul utilisateur, mais une communauté de personnes.

Diagramme de conteneur CloudKit

À l’intérieur d’un conteneur, la base de données publique est d’abord et avant tout. C’est là que vit et se mêle toute l’information publique. En outre, il existe plusieurs bases de données privées individuelles pour chaque utilisateur de l’application.

Lors de l’exécution sur un appareil iOS, l’application n’aura accès qu’aux informations de l’utilisateur iCloud actuellement connecté. Par conséquent, la vue de l’application du conteneur se présente comme suit :

Vue des applications du conteneur

Il peut uniquement voir la base de données publique et la base de données privée associée à l’utilisateur iCloud actuellement connecté.

Les bases de données sont exposées dans CloudKit Framework via la CKDatabase classe . Chaque application a accès à deux bases de données : la base de données publique et la base de données privée.

Le conteneur est le point d’entrée initial dans CloudKit. Le code suivant peut être utilisé pour accéder à la base de données publique et privée à partir du conteneur par défaut de l’application :

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;

Voici les différences entre les types de base de données :

Base de données publique Base de données privée
Type de données Données partagées Données de l’utilisateur actuel
Quota Pris en compte dans le quota du développeur Pris en compte dans le quota de l’utilisateur
Autorisations par défaut Lisible dans le monde Lisible par l’utilisateur
Autorisations de modification Rôles de tableau de bord iCloud via un niveau de classe d’enregistrement N/A

Enregistrements

Les conteneurs contiennent des bases de données, et à l’intérieur des bases de données sont des enregistrements. Les enregistrements sont le mécanisme dans lequel les données structurées sont déplacées vers et depuis CloudKit :

Les conteneurs contiennent des bases de données, et à l’intérieur des bases de données sont des enregistrements

Les enregistrements sont exposés dans CloudKit Framework via la CKRecord classe, qui encapsule les paires clé-valeur. Une instance d’un objet dans une application équivaut à un CKRecord dans CloudKit. En outre, chacun CKRecord possède un type d’enregistrement, qui est équivalent à la classe d’un objet.

Les enregistrements ayant un schéma juste-à-temps, les données sont décrites à CloudKit avant d’être transmises pour traitement. À partir de ce moment, CloudKit interprétera les informations et gérera la logistique du stockage et de la récupération de l’enregistrement.

La CKRecord classe prend également en charge un large éventail de métadonnées. Par exemple, un enregistrement contient des informations sur le moment où il a été créé et l’utilisateur qui l’a créé. Un enregistrement contient également des informations sur le moment où il a été modifié pour la dernière fois et l’utilisateur qui l’a modifié.

Les enregistrements contiennent la notion d’étiquette de modification. Il s’agit d’une version précédente d’une révision d’un enregistrement donné. La balise de modification est utilisée comme un moyen léger de déterminer si le client et le serveur ont la même version d’un enregistrement donné.

Comme indiqué ci-dessus, CKRecords encapsuler les paires clé-valeur et, par conséquent, les types de données suivants peuvent être stockés dans un enregistrement :

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

En plus des types à valeur unique, un enregistrement peut contenir un tableau homogène de l’un des types listés ci-dessus.

Le code suivant peut être utilisé pour créer un enregistrement et le stocker dans une base de données :

using CloudKit;
//...

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

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

Zones d’enregistrement

Les enregistrements n’existent pas seuls dans une base de données donnée . Des groupes d’enregistrements existent ensemble à l’intérieur d’une zone d’enregistrement. Les zones d’enregistrement peuvent être considérées comme des tables dans des bases de données relationnelles traditionnelles :

Des groupes d’enregistrements existent ensemble à l’intérieur d’une zone d’enregistrement

Il peut y avoir plusieurs enregistrements dans une zone d’enregistrement donnée et plusieurs zones d’enregistrement au sein d’une base de données donnée. Chaque base de données contient une zone d’enregistrement par défaut :

Chaque base de données contient une zone d’enregistrement par défaut et une zone personnalisée

C’est là que les enregistrements sont stockés par défaut. En outre, des zones d’enregistrement personnalisées peuvent être créées. Les zones d’enregistrement représentent la granularité de base à laquelle les commits atomiques et les Change Tracking sont effectués.

Identificateurs d’enregistrement

Les identificateurs d’enregistrement sont représentés sous forme de tuple, contenant à la fois un nom d’enregistrement fourni par le client et la zone dans laquelle l’enregistrement existe. Les identificateurs d’enregistrement présentent les caractéristiques suivantes :

  • Ils sont créés par l’application cliente.
  • Ils sont entièrement normalisés et représentent l’emplacement spécifique de l’enregistrement.
  • En affectant l’ID unique d’un enregistrement dans une base de données étrangère au nom de l’enregistrement, ils peuvent être utilisés pour ponter des bases de données locales qui ne sont pas stockées dans CloudKit.

Lorsque les développeurs créent des enregistrements, ils peuvent choisir de transmettre un identificateur d’enregistrement. Si aucun identificateur d’enregistrement n’est spécifié, un UUID est automatiquement créé et affecté à l’enregistrement.

Lorsque les développeurs créent des identificateurs d’enregistrement, ils peuvent choisir de spécifier la zone d’enregistrement à laquelle chaque enregistrement appartiendra. Si aucune n’est spécifiée, la zone d’enregistrement par défaut est utilisée.

Les identificateurs d’enregistrement sont exposés dans CloudKit Framework via la CKRecordID classe . Le code suivant peut être utilisé pour créer un identificateur d’enregistrement :

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

Références

Les références fournissent des relations entre les enregistrements associés au sein d’une base de données donnée :

Les références fournissent des relations entre les enregistrements associés au sein d’une base de données donnée

Dans l’exemple ci-dessus, parents possèdent des enfants afin que l’enfant soit un enregistrement enfant de l’enregistrement parent. La relation va de l’enregistrement enfant à l’enregistrement parent et est appelée référence arrière.

Les références sont exposées dans CloudKit Framework via la CKReference classe . Ils permettent au serveur iCloud de comprendre la relation entre les enregistrements.

Les références fournissent le mécanisme derrière les suppressions en cascade. Si un enregistrement parent est supprimé de la base de données, tous les enregistrements enfants (comme spécifié dans une relation) sont automatiquement supprimés de la base de données.

Notes

Des pointeurs pendant l’utilisation de CloudKit sont possibles. Par exemple, au moment où l’application a extrait une liste de pointeurs d’enregistrement, sélectionné un enregistrement, puis demandé l’enregistrement, il se peut que l’enregistrement n’existe plus dans la base de données. Une application doit être codée pour gérer cette situation correctement.

Bien qu’elles ne soient pas obligatoires, les références en arrière sont recommandées lors de l’utilisation de CloudKit Framework. Apple a affiné le système pour en faire le type de référence le plus efficace.

Lors de la création d’une référence, le développeur peut fournir un enregistrement qui est déjà en mémoire ou créer une référence à un identificateur d’enregistrement. Si vous utilisez un identificateur d’enregistrement et que la référence spécifiée n’existe pas dans la base de données, un pointeur Dangling est créé.

Voici un exemple de création d’une référence sur un enregistrement connu :

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

Éléments multimédias

Les ressources permettent de charger un fichier de données volumineuses et non structurées sur iCloud et de les associer à un enregistrement donné :

Les ressources permettent de charger un fichier de données volumineuses et non structurées sur iCloud et de les associer à un enregistrement donné

Sur le client, un CKRecord est créé qui décrit le fichier qui va être chargé sur le serveur iCloud. Un CKAsset est créé pour contenir le fichier et est lié à l’enregistrement le décrivant.

Lorsque le fichier est chargé sur le serveur, l’enregistrement est placé dans la base de données et le fichier est copié dans une base de données de stockage en bloc spéciale. Un lien est créé entre le pointeur d’enregistrement et le fichier chargé.

Les ressources sont exposées dans CloudKit Framework via la CKAsset classe et sont utilisées pour stocker des données volumineuses et non structurées. Étant donné que le développeur ne souhaite jamais avoir de données volumineuses et non structurées en mémoire, les ressources sont implémentées à l’aide de fichiers sur le disque.

Les ressources appartiennent aux enregistrements, ce qui permet de récupérer les ressources à partir d’iCloud en utilisant l’enregistrement comme pointeur. De cette façon, le serveur peut garbage collect assets lorsque l’enregistrement propriétaire de la ressource est supprimé.

Étant donné que CKAssets sont destinés à gérer des fichiers de données volumineux, Apple a conçu CloudKit pour charger et télécharger efficacement les ressources.

Le code suivant peut être utilisé pour créer une ressource et l’associer à l’enregistrement :

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

Nous avons maintenant couvert tous les objets fondamentaux dans CloudKit. Les conteneurs sont associés aux applications et contiennent des bases de données. Les bases de données contiennent des enregistrements regroupés en zones d’enregistrement et pointés par des identificateurs d’enregistrement. Les relations parent-enfant sont définies entre les enregistrements à l’aide de références. Enfin, des fichiers volumineux peuvent être chargés et associés aux enregistrements à l’aide de ressources.

CloudKit Convenience API

Apple propose deux ensembles d’API différents pour l’utilisation de CloudKit :

  • API opérationnelle : offre toutes les fonctionnalités de CloudKit. Pour les applications plus complexes, cette API fournit un contrôle affiné sur CloudKit.
  • API pratique : offre un sous-ensemble commun et préconfiguré de fonctionnalités CloudKit. Il fournit une solution pratique et facile d’accès pour inclure des fonctionnalités CloudKit dans une application iOS.

L’API Convenience est généralement le meilleur choix pour la plupart des applications iOS et Apple suggère de commencer par elle. Le reste de cette section couvre les rubriques suivantes de l’API Commodité :

  • Enregistrement d’un enregistrement.
  • Extraction d’un enregistrement.
  • Mise à jour d’un enregistrement.

Code d’installation courant

Avant de commencer à utiliser l’API CloudKit Convenience, un code d’installation standard est requis. Commencez par modifier le fichier de l’application AppDelegate.cs et faites-le ressembler à ce qui suit :

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");
        }
    }
}

Le code ci-dessus expose les bases de données CloudKit publiques et privées sous forme de raccourcis pour faciliter leur utilisation dans le reste de l’application.

Ensuite, ajoutez le code suivant à n’importe quel conteneur de vue qui utilisera CloudKit :

using CloudKit;
//...

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

Cela ajoute un raccourci pour accéder aux AppDelegate raccourcis de base de données publique et privée créés ci-dessus et y accéder.

Une fois ce code en place, examinons l’implémentation de l’API CloudKit Convenience dans une application Xamarin iOS 8.

Enregistrement d’un enregistrement

À l’aide du modèle présenté ci-dessus lors de la présentation des enregistrements, le code suivant crée un enregistrement et utilise l’API Convenience pour l’enregistrer dans la base de données publique :

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) {
        ...
    }
});

Trois points à noter sur le code ci-dessus :

  1. En appelant la SaveRecord méthode de PublicDatabase, le développeur n’a pas besoin de spécifier la façon dont les données sont envoyées, la zone dans laquelle elles sont écrites, etc. L’API Convenience s’occupe elle-même de tous ces détails.
  2. L’appel est asynchrone et fournit une routine de rappel une fois l’appel terminé, avec succès ou échec. Si l’appel échoue, un message d’erreur est fourni.
  3. CloudKit ne fournit pas de stockage/persistance locale ; il s’agit d’un support de transfert uniquement. Par conséquent, lorsqu’une demande d’enregistrement est effectuée, elle est immédiatement envoyée aux serveurs iCloud.

Notes

En raison de la nature « perte » des communications réseau mobiles, où les connexions sont constamment supprimées ou interrompues, l’une des premières considérations que le développeur doit prendre en compte lors de l’utilisation de CloudKit est la gestion des erreurs.

Extraction d’un enregistrement

Une fois qu’un enregistrement a été créé et correctement stocké sur le serveur iCloud, utilisez le code suivant pour récupérer l’enregistrement :

// 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) {
        ...
    }
});

Tout comme lors de l’enregistrement de l’enregistrement, le code ci-dessus est asynchrone, simple et nécessite une gestion des erreurs importante.

Mise à jour d'un enregistrement

Une fois qu’un enregistrement a été extrait à partir des serveurs iCloud, le code suivant peut être utilisé pour modifier l’enregistrement et enregistrer les modifications dans la base de données :

// 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) {
                 ...
            }
        });
    }
});

La FetchRecord méthode de retourne PublicDatabase un CKRecord si l’appel a réussi. L’application modifie ensuite l’enregistrement et appelle SaveRecord à nouveau pour réécrire les modifications dans la base de données.

Cette section présente le cycle classique qu’une application utilisera lors de l’utilisation de l’API CloudKit Convenience. L’application enregistrera les enregistrements dans iCloud, récupérera ces enregistrements à partir d’iCloud, modifiera les enregistrements et enregistrera ces modifications dans iCloud.

Conception pour la scalabilité

Jusqu’à présent, cet article a examiné le stockage et la récupération de l’ensemble du modèle objet d’une application à partir des serveurs iCloud, chaque fois qu’il va être utilisé. Bien que cette approche fonctionne bien avec une petite quantité de données et une très petite base d’utilisateurs, elle ne fonctionne pas correctement lorsque la quantité d’informations et/ou de base d’utilisateurs augmente.

Big Data, appareil minuscule

Plus une application devient populaire, plus il y a de données dans la base de données et moins il est possible d’avoir un cache de ces données entières sur l’appareil. Les techniques suivantes peuvent être utilisées pour résoudre ce problème :

  • Conserver les données volumineuses dans le cloud : CloudKit a été conçu pour gérer efficacement les données volumineuses.
  • Le client ne doit afficher qu’une partie de ces données : réduire le minimum de données nécessaires pour gérer une tâche à un moment donné.
  • Les vues clientes peuvent changer : étant donné que chaque utilisateur a des préférences différentes, la tranche de données affichée peut changer d’utilisateur à utilisateur et la vue individuelle de l’utilisateur d’une tranche donnée peut être différente.
  • Le client utilise des requêtes pour concentrer le point de vue : les requêtes permettent à l’utilisateur d’afficher un petit sous-ensemble d’un jeu de données plus volumineux qui existe dans le cloud.

Requêtes

Comme indiqué ci-dessus, les requêtes permettent au développeur de sélectionner un petit sous-ensemble du jeu de données plus volumineux qui existe dans le cloud. Les requêtes sont exposées dans CloudKit Framework via la CKQuery classe .

Une requête combine trois éléments différents : un type d’enregistrement ( RecordType), un prédicat ( NSPredicate) et, éventuellement, un descripteur de tri ( NSSortDescriptors). CloudKit prend en charge la majeure partie de NSPredicate.

Prédicats pris en charge

CloudKit prend en charge les types suivants de lorsque vous utilisez des NSPredicates requêtes :

  1. Correspondance Enregistrements où le nom est égal à une valeur stockée dans une variable :

    NSPredicate.FromFormat(string.Format("name = '{0}'", recordName))
    
  2. Permet à la correspondance d’être basée sur une valeur de clé dynamique, de sorte que la clé n’ait pas besoin d’être connu au moment de la compilation :

    NSPredicate.FromFormat(string.Format("{0} = '{1}'", key, value))
    
  3. Enregistrements correspondants où la valeur de l’enregistrement est supérieure à la valeur donnée :

    NSPredicate.FromFormat(string.Format("start > {0}", (NSDate)date))
    
  4. Correspondance Des enregistrements où l’emplacement de l’enregistrement se trouve à moins de 100 mètres de l’emplacement donné :

    var location = new CLLocation(37.783,-122.404);
    var predicate = NSPredicate.FromFormat(string.Format("distanceToLocation:fromLocation(Location,{0}) < 100", location));
    
  5. CloudKit prend en charge une recherche avec jetons. Cet appel crée deux jetons, l’un pour after et l’autre pour session. Il retourne un enregistrement qui contient ces deux jetons :

    NSPredicate.FromFormat(string.Format("ALL tokenize({0}, 'Cdl') IN allTokens", "after session"))
    
  6. CloudKit prend en charge les prédicats composés joints à l’aide de l’opérateur AND .

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

Création de requêtes

Le code suivant peut être utilisé pour créer un CKQuery dans une application Xamarin iOS 8 :

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

Tout d’abord, il crée un prédicat pour sélectionner uniquement les enregistrements qui correspondent à un nom donné. Ensuite, il crée une requête qui sélectionnera Enregistrements du type d’enregistrement donné qui correspondent au prédicat.

Exécution d’une requête

Une fois qu’une requête a été créée, utilisez le code suivant pour effectuer la requête et traiter les enregistrements retournés :

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];
        }
    }
});

Le code ci-dessus prend la requête créée ci-dessus et l’exécute sur la base de données publique. Étant donné qu’aucune zone d’enregistrement n’est spécifiée, toutes les zones sont recherchées. Si aucune erreur ne s’est produite, un tableau de CKRecords est retourné correspondant aux paramètres de la requête.

La façon de penser aux requêtes est qu’il s’agit de sondages et qu’elles sont idéales pour trancher des jeux de données volumineux. Toutefois, les requêtes ne sont pas adaptées aux jeux de données volumineux, principalement statiques, pour les raisons suivantes :

  • Ils sont mauvais pour l’autonomie de la batterie de l’appareil.
  • Elles sont mauvaises pour le trafic réseau.
  • Ils sont mauvais pour l’expérience utilisateur, car les informations qu’ils voient sont limitées par la fréquence à laquelle l’application interroge la base de données. Aujourd’hui, les utilisateurs s’attendent à recevoir des notifications Push quand quelque chose change.

Abonnements

Lorsque vous traitez des jeux de données volumineux, principalement statiques, la requête ne doit pas être effectuée sur l’appareil client, mais elle doit s’exécuter sur le serveur pour le compte du client. La requête doit s’exécuter en arrière-plan et doit être exécutée après chaque enregistrement, que ce soit par l’appareil actuel ou un autre appareil touchant la même base de données.

Enfin, une notification Push doit être envoyée à chaque appareil attaché à la base de données lors de l’exécution de la requête côté serveur.

Les abonnements sont exposés dans CloudKit Framework via la CKSubscription classe . Ils combinent un type d’enregistrement ( RecordType), un prédicat ( NSPredicate) et une notification Push Apple ( Push).

Notes

Les push CloudKit sont légèrement augmentés, car ils contiennent une charge utile contenant des informations spécifiques à CloudKit, telles que la cause de l’envoi push.

Fonctionnement des abonnements

Avant d’implémenter l’abonnement dans le code C#, prenons une vue d’ensemble rapide du fonctionnement des abonnements :

Vue d’ensemble du fonctionnement des abonnements

Le graphique ci-dessus montre le processus d’abonnement classique comme suit :

  1. L’appareil client crée un abonnement contenant l’ensemble des conditions qui déclencheront l’abonnement et une notification Push qui sera envoyée lorsque le déclencheur se produit.
  2. L’abonnement est envoyé à la base de données où il est ajouté à la collection d’abonnements existants.
  3. Un deuxième appareil crée un enregistrement et l’enregistre dans la base de données.
  4. La base de données recherche dans sa liste d’abonnements pour voir si le nouvel enregistrement correspond à l’une de leurs conditions.
  5. Si une correspondance est trouvée, la notification Push est envoyée à l’appareil qui a inscrit l’abonnement avec des informations sur l’enregistrement qui a provoqué son déclenchement.

Une fois ces connaissances en place, examinons la création d’abonnements dans une application Xamarin iOS 8.

Création d’abonnements

Le code suivant peut être utilisé pour créer un abonnement :

// 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;

Tout d’abord, il crée un prédicat qui fournit la condition pour déclencher l’abonnement. Ensuite, il crée l’abonnement par rapport à un type d’enregistrement spécifique et définit l’option de lorsque le déclencheur est testé. Enfin, il définit le type de notification qui se produira lorsque l’abonnement est déclenché et l’attache à l’abonnement.

Enregistrement des abonnements

Une fois l’abonnement créé, le code suivant l’enregistrera dans la base de données :

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

    }
});

À l’aide de l’API Convenience, l’appel est asynchrone, simple et permet une gestion facile des erreurs.

Gestion des notifications Push

Si le développeur a déjà utilisé les notifications Push Apple (APS), le processus de traitement des notifications générées par CloudKit doit être familier.

Dans , AppDelegate.csremplacez la ReceivedRemoteNotification classe comme suit :

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;
    }
}

Le code ci-dessus demande à CloudKit d’analyser userInfo dans une notification CloudKit. Ensuite, des informations sur l’alerte sont extraites. Enfin, le type de notification est testé et la notification est gérée en conséquence.

Cette section a montré comment répondre au problème Big Data, Tiny Device présenté ci-dessus à l’aide de requêtes et d’abonnements. L’application laissera ses données volumineuses dans le cloud et utilisera ces technologies pour fournir des vues dans ce jeu de données.

Comptes d’utilisateur CloudKit

Comme indiqué au début de cet article, CloudKit repose sur l’infrastructure iCloud existante. La section suivante décrit en détail comment les comptes sont exposés à un développeur à l’aide de l’API CloudKit.

Authentification

Lorsque vous traitez des comptes d’utilisateur, la première considération est l’authentification. CloudKit prend en charge l’authentification via l’utilisateur iCloud actuellement connecté sur l’appareil. L’authentification se déroule en arrière-plan et est gérée par iOS. De cette façon, les développeurs n’ont jamais à se soucier des détails de l’implémentation de l’authentification. Ils testent uniquement pour voir si un utilisateur est connecté.

Informations de compte utilisateur

CloudKit fournit les informations utilisateur suivantes au développeur :

  • Identité : un moyen d’identifier l’utilisateur de manière unique.
  • Métadonnées : possibilité d’enregistrer et de récupérer des informations sur les utilisateurs.
  • Confidentialité : toutes les informations sont traitées dans un manoir soucieux de la confidentialité. Rien n’est exposé, sauf si l’utilisateur l’a accepté.
  • Découverte : permet aux utilisateurs de découvrir leurs amis qui utilisent la même application.

Ensuite, nous allons examiner ces sujets en détail.

Identité

Comme indiqué ci-dessus, CloudKit permet à l’application d’identifier de manière unique un utilisateur donné :

Identification unique d’un utilisateur donné

Une application cliente s’exécute sur les appareils d’un utilisateur et sur toutes les bases de données privées utilisateur spécifiques à l’intérieur du conteneur CloudKit. L’application cliente va être liée à l’un de ces utilisateurs spécifiques. Cela est basé sur l’utilisateur connecté à iCloud localement sur l’appareil.

Étant donné que cela provient d’iCloud, il existe un magasin complet d’informations utilisateur. Et étant donné qu’iCloud héberge réellement le conteneur, il peut mettre en corrélation les utilisateurs. Dans le graphique ci-dessus, l’utilisateur dont le compte user@icloud.com iCloud est lié au client actuel.

Sur une base conteneur par conteneur, un ID utilisateur unique généré de manière aléatoire est créé et associé au compte iCloud de l’utilisateur (adresse e-mail). Cet ID d’utilisateur est retourné à l’application et peut être utilisé de la manière que le développeur juge bon.

Notes

Différentes applications s’exécutant sur le même appareil pour le même utilisateur iCloud auront des ID d’utilisateur différents, car elles sont connectées à différents conteneurs CloudKit.

Le code suivant obtient l’ID utilisateur CloudKit de l’utilisateur iCloud actuellement connecté sur l’appareil :

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;
    }
});

Le code ci-dessus demande au conteneur CloudKit de fournir l’ID de l’utilisateur actuellement connecté. Étant donné que ces informations proviennent du serveur iCloud, l’appel est asynchrone et la gestion des erreurs est requise.

Métadonnées

Chaque utilisateur dans CloudKit a des métadonnées spécifiques qui les décrivent. Ces métadonnées sont représentées sous la forme d’un enregistrement CloudKit :

Chaque utilisateur dans CloudKit a des métadonnées spécifiques qui les décrivent

Si vous examinez la base de données privée pour un utilisateur spécifique d’un conteneur, il existe un enregistrement qui définit cet utilisateur. Il existe de nombreux enregistrements utilisateur à l’intérieur de la base de données publique, un pour chaque utilisateur du conteneur. L’un d’eux aura un ID d’enregistrement qui correspond à l’ID d’enregistrement de l’utilisateur actuellement connecté.

Les enregistrements utilisateur dans la base de données publique sont lisibles dans le monde entier. Ils sont traités, pour la plupart, comme un enregistrement ordinaire et ont un type de CKRecordTypeUserRecord. Ces enregistrements sont réservés par le système et ne sont pas disponibles pour les requêtes.

Utilisez le code suivant pour accéder à un enregistrement utilisateur :

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;
    }
});

Le code ci-dessus demande à la base de données publique de retourner l’enregistrement utilisateur de l’utilisateur auquel nous avons accédé ci-dessus. Étant donné que ces informations proviennent du serveur iCloud, l’appel est asynchrone et la gestion des erreurs est requise.

Confidentialité

CloudKit a été conçu, par défaut, pour protéger la confidentialité de l’utilisateur actuellement connecté. Aucune information d’identification personnelle concernant l’utilisateur n’est exposée par défaut. Dans certains cas, l’application nécessite des informations limitées sur l’utilisateur.

Dans ce cas, l’application peut demander à l’utilisateur de divulguer ces informations. Une boîte de dialogue est présentée à l’utilisateur pour lui demander d’accepter d’exposer les informations de son compte.

Découverte

En supposant que l’utilisateur a choisi d’autoriser l’application à limiter l’accès aux informations de son compte d’utilisateur, il peut être découvert par d’autres utilisateurs de l’application :

Un utilisateur peut être détectable par d’autres utilisateurs de l’application

L’application cliente parle à un conteneur, et le conteneur parle d’iCloud pour accéder aux informations utilisateur. L’utilisateur peut fournir une adresse e-mail et la découverte peut être utilisée pour récupérer des informations sur l’utilisateur. Si vous le souhaitez, l’ID utilisateur peut également être utilisé pour découvrir des informations sur l’utilisateur.

CloudKit permet également de découvrir des informations sur n’importe quel utilisateur qui peut être ami de l’utilisateur iCloud actuellement connecté en interrogeant l’intégralité du carnet d’adresses. Le processus CloudKit extrait le carnet de contacts de l’utilisateur et utilise les adresses e-mail pour voir s’il peut trouver les autres utilisateurs de l’application qui correspondent à ces adresses.

Cela permet à l’application de tirer parti du carnet de contacts de l’utilisateur sans lui fournir l’accès ou demander à l’utilisateur d’approuver l’accès aux contacts. À aucun moment les informations de contact ne sont mises à la disposition de l’application, seul le processus CloudKit y a accès.

Pour résumer, il existe trois types d’entrées différents disponibles pour la découverte d’utilisateurs :

  • ID d’enregistrement utilisateur : la découverte peut être effectuée par rapport à l’ID d’utilisateur de l’utilisateur CloudKit actuellement connecté.
  • Adresse Email utilisateur : l’utilisateur peut fournir une adresse e-mail qui peut être utilisée pour la découverte.
  • Carnet de contacts : le carnet d’adresses de l’utilisateur peut être utilisé pour découvrir les utilisateurs de l’application qui ont la même adresse e-mail que celle indiquée dans leurs contacts.

La découverte d’utilisateurs retourne les informations suivantes :

  • ID d’enregistrement utilisateur : ID unique d’un utilisateur dans la base de données publique.
  • Prénom et nom : tels qu’ils sont stockés dans la base de données publique.

Ces informations ne seront retournées que pour les utilisateurs qui ont choisi la découverte.

Le code suivant découvre des informations sur l’utilisateur actuellement connecté à iCloud sur l’appareil :

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;
    }
});

Utilisez le code suivant pour interroger tous les utilisateurs du carnet de contacts :

// 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];
        }
    }
});

Dans cette section, nous avons abordé les quatre principaux domaines d’accès au compte d’utilisateur que CloudKit peut fournir à une application. De l’obtention de l’identité et des métadonnées de l’utilisateur aux stratégies de confidentialité intégrées à CloudKit et enfin, à la possibilité de découvrir d’autres utilisateurs de l’application.

Les environnements de développement et de production

CloudKit fournit des environnements de développement et de production distincts pour les types d’enregistrements et les données d’une application. L’environnement de développement est un environnement plus flexible qui est disponible uniquement pour les membres d’une équipe de développement. Lorsqu’une application ajoute un nouveau champ à un enregistrement et enregistre cet enregistrement dans l’environnement de développement, le serveur met automatiquement à jour les informations de schéma.

Le développeur peut utiliser cette fonctionnalité pour apporter des modifications à un schéma pendant le développement, ce qui fait gagner du temps. Une mise en garde est qu’une fois qu’un champ a été ajouté à un enregistrement, le type de données associé à ce champ ne peut pas être modifié par programmation. Pour modifier le type d’un champ, le développeur doit supprimer le champ dans le tableau de bord CloudKit et l’ajouter à nouveau avec le nouveau type.

Avant de déployer l’application, le développeur peut migrer son schéma et ses données vers l’environnement de production à l’aide du tableau de bord CloudKit. Lors de l’exécution sur l’environnement de production, le serveur empêche une application de modifier le schéma par programmation. Le développeur peut toujours apporter des modifications avec le tableau de bord CloudKit , mais les tentatives d’ajout de champs à un enregistrement dans l’environnement de production entraînent des erreurs.

Notes

Le simulateur iOS fonctionne uniquement avec l’environnement de développement. Lorsque le développeur est prêt à tester une application dans un environnement de production, un appareil iOS physique est requis.

Expédition d’une application compatible Avec CloudKit

Avant d’expédier une application qui utilise CloudKit, elle doit être configurée pour cibler l’environnement CloudKit de production ou l’application sera rejetée par Apple.

Effectuez les actions suivantes :

  1. Dans Visual Studio pour Ma, compilez l’application pour Libérer>l’appareil iOS :

    Compiler l’application pour la mise en production

  2. Dans le menu Générer , sélectionnez Archiver :

    Sélectionner Archiver

  3. L’archive sera créée et affichée dans Visual Studio pour Mac :

    L’archive sera créée et affichée

  4. Démarrez Xcode.

  5. Dans le menu Fenêtre , sélectionnez Organisateur :

    Sélectionner l’organisateur

  6. Sélectionnez l’archive de l’application, puis cliquez sur le bouton Exporter... :

    Archive de l’application

  7. Sélectionnez une méthode à exporter, puis cliquez sur le bouton Suivant :

    Sélectionner une méthode pour l’exportation

  8. Sélectionnez l’équipe de développement dans la liste déroulante, puis cliquez sur le bouton Choisir :

    Sélectionnez l’équipe de développement dans la liste déroulante

  9. Sélectionnez Production dans la liste déroulante, puis cliquez sur le bouton Suivant :

    Sélectionnez Production dans la liste déroulante

  10. Passez en revue le paramètre et cliquez sur le bouton Exporter :

    Passer en revue le paramètre

  11. Choisissez un emplacement pour générer le fichier d’application .ipa résultant.

Le processus est similaire pour envoyer l’application directement à iTunes Connect. Cliquez simplement sur le bouton Envoyer... au lieu de l’option Exporter... après avoir sélectionné une archive dans la fenêtre Organisateur.

Quand utiliser CloudKit

Comme nous l’avons vu dans cet article, CloudKit fournit un moyen simple pour une application de stocker et de récupérer des informations à partir des serveurs iCloud. Cela étant dit, CloudKit n’est pas obsolète ou déprécié aucun des outils ou frameworks existants.

Cas d'utilisation

Les cas d’usage suivants doivent aider le développeur à décider quand utiliser une infrastructure ou une technologie iCloud spécifique :

  • iCloud Key-Value Store : conserve de manière asynchrone une petite quantité de données à jour et est idéal pour utiliser les préférences d’application. Toutefois, il est limité pour une très petite quantité d’informations.
  • iCloud Drive : s’appuie sur les API de documents iCloud existantes et fournit une API simple pour synchroniser les données non structurées à partir du système de fichiers. Il fournit un cache hors connexion complet sur Mac OS X et est idéal pour les applications centrées sur les documents.
  • Données principales iCloud : permet de répliquer des données entre tous les appareils de l’utilisateur. Les données sont mono-utilisateur et sont idéales pour maintenir des données structurées et privées synchronisées.
  • CloudKit : fournit des données publiques à la fois en structure et en bloc et est capable de gérer à la fois des jeux de données volumineux et des fichiers non structurés volumineux. Il est lié au compte iCloud de l’utilisateur et fournit un transfert de données dirigé par le client.

En gardant ces cas d’usage à l’esprit, le développeur doit choisir la technologie iCloud appropriée pour fournir à la fois les fonctionnalités d’application requises actuelles et fournir une bonne scalabilité pour une croissance future.

Résumé

Cet article présente rapidement l’API CloudKit. Il a montré comment approvisionner et configurer une application iOS Xamarin pour utiliser CloudKit. Il a couvert les fonctionnalités de l’API CloudKit Convenience. Il a montré comment concevoir une application compatible Avec CloudKit pour la scalabilité à l’aide de requêtes et d’abonnements. Enfin, il a affiché les informations de compte d’utilisateur exposées à une application par CloudKit.