CloudKit en Xamarin.iOS
El marco CloudKit simplifica el desarrollo de aplicaciones que acceden a iCloud. Esto incluye la recuperación de los datos de la aplicación y los derechos de los recursos, así como la capacidad de almacenar de forma segura la información de la aplicación. Este kit proporciona a los usuarios una capa de anonimidad al permitir el acceso a las aplicaciones con sus IDs de iCloud sin compartir información personal.
Los desarrolladores pueden centrarse en sus aplicaciones del lado cliente y dejar que iCloud elimine la necesidad de escribir lógica de aplicación del lado servidor. CloudKit proporciona autenticación, bases de datos privadas y públicas, y datos estructurados y servicios de almacenamiento de recursos.
Importante
Apple proporciona herramientas para ayudar a los desarrolladores a tratar correctamente el Reglamento general de protección de datos (RGPD) de la Unión Europea.
Requisitos
Se requiere lo siguiente para completar los pasos presentados en este artículo:
- Xcode y el SDK de iOS: las API Xcode e iOS 8 de Apple deben instalarse y configurarse en el equipo del desarrollador.
- Visual Studio para Mac: la versión más reciente de Visual Studio para Mac debe instalarse y configurarse en el dispositivo del usuario.
- Dispositivo iOS 8: un dispositivo iOS que ejecuta la versión más reciente de iOS 8 para pruebas.
¿Qué es CloudKit?
CloudKit es una manera de proporcionar al desarrollador acceso a los servidores de iCloud. Proporciona la base para iCloud Drive y iCloud Photo Library. CloudKit es compatible con dispositivos macOS e iOS.
CloudKit usa la infraestructura de la cuenta de iCloud. Si hay un usuario que ha iniciado sesión en una cuenta de iCloud en el dispositivo, CloudKit usará su identificador para identificar al usuario. Si no hay ninguna cuenta disponible, se proporciona acceso de solo lectura limitado.
CloudKit admite el concepto de bases de datos públicas y privadas. Las bases de datos públicas proporcionan un "resumen" de todos los datos a los que el usuario tiene acceso. Las bases de datos privadas están diseñadas para almacenar los datos privados enlazados a un usuario específico.
CloudKit admite datos estructurados y masivos. Es capaz de controlar las transferencias de archivos de gran tamaño sin problemas. CloudKit se encarga de transferir archivos grandes de forma eficaz hacia y desde los servidores de iCloud en segundo plano, lo que permite al desarrollador centrarse en otras tareas.
Nota:
Es importante tener en cuenta que CloudKit es una tecnología de transporte. No proporciona ninguna persistencia; solo permite que una aplicación envíe y reciba información de los servidores de forma eficaz.
En el momento de redactar este artículo, Apple inicialmente proporciona CloudKit de forma gratuita con un límite alto en el ancho de banda y la capacidad de almacenamiento. En el caso de proyectos o aplicaciones más grandes con una base de usuarios de gran tamaño, Apple ha dado a entender que se proporciona una escala de precios asequible.
Habilitación de CloudKit en una aplicación xamarin
Para que una aplicación xamarin pueda usar el marco CloudKit, la aplicación debe aprovisionarse correctamente como se detalla en las guías Trabajar con funcionalidades y Trabajar con derechos.
Para acceder a CloudKit, el archivo Entitlements.plist debe incluir los permisos Habilitar iCloud,Almacenamiento de clave-valory CloudKit.
Aplicación de ejemplo
En el ejemplo CloudKitAtlas se muestra cómo usar CloudKit con Xamarin. En los pasos siguientes se muestra cómo configurar el ejemplo; requiere valores adicionales más allá de lo que se requiere solo para CloudKit:
- Abra el proyecto en Visual Studio para Mac o Visual Studio.
- En el Explorador de soluciones, abra el archivo Info.plist y asegúrese de que el identificador de agrupación coincide con el que se definió en el identificador de aplicación creado como parte de la configuración de aprovisionamiento.
- Desplácese hacia abajo hasta la parte inferior del archivo Info.plist y seleccione Modosen segundo plano habilitados, Actualizaciones de ubicación y Notificaciones remotas.
- Haga clic con el botón derecho en el proyecto de iOS en la solución y seleccione Opciones.
- Seleccione Firma de lote de iOS,seleccione la identidad del desarrollador y el perfil de aprovisionamiento creados anteriormente.
- Asegúrese de que Entitlements.plist incluyeHabilitar iCloud,Almacenamiento de clave-valory CloudKit.
- Asegúrese de que existe el contenedor Ubiquity para la aplicación. Ejemplo:
iCloud.com.your-company.CloudKitAtlas - Guarde los cambios en el archivo.
Con esta configuración, la aplicación de ejemplo ya está lista para acceder a las API de CloudKit Framework, así como a los servicios de notificación, ubicación y fondo.
Introducción a la API de CloudKit
Antes de implementar CloudKit en una aplicación de Xamarin iOS, en este artículo se tratarán los aspectos básicos de CloudKit Framework, que incluirán los temas siguientes:
- Contenedores: silos aislados de comunicaciones de iCloud.
- Bases de datos: las bases de datos públicas y privadas están disponibles para la aplicación.
- Registros: mecanismo en el que se mueven los datos estructurados hacia y desde CloudKit.
- Zonas de registro: son grupos de registros.
- Identificadores de registro: están totalmente normalizados y representan la ubicación específica del registro.
- Referencia: proporcione relaciones de elementos primarios y secundarios entre los registros relacionados dentro de una base de datos determinada.
- Recursos: permite que el archivo de datos grandes y no estructurados se cargue en iCloud y se asocie a un registro determinado.
Contenedores
Una aplicación determinada que se ejecuta en un dispositivo iOS siempre se ejecuta en paralelo con otras aplicaciones y servicios de ese dispositivo. En el dispositivo cliente, la aplicación se va a instalar en silo o a espacio aislado de alguna manera. En algunos casos, se trata de un espacio aislado literal y, en otros, la aplicación simplemente se ejecuta en su propio espacio de memoria.
El concepto de tomar una aplicación cliente y ejecutarla separada de otros clientes es muy eficaz y proporciona las siguientes ventajas:
- Seguridad: una aplicación no puede interferir con otras aplicaciones cliente ni con el propio sistema operativo.
- Estabilidad: si la aplicación cliente se bloquea, no puede sacar otras aplicaciones del sistema operativo.
- Privacidad: cada aplicación cliente tiene acceso limitado a la información personal almacenada en el dispositivo.
CloudKit se diseñó para proporcionar las mismas ventajas que las enumeradas anteriormente y aplicarlas al trabajo con información basada en la nube:
Al igual que la aplicación que se ejecuta en el dispositivo, también lo son las comunicaciones de la aplicación con iCloud. Cada uno de estos silos de comunicación diferentes se denomina Contenedores.
Los contenedores se exponen en CloudKit Framework a través de la CKContainer clase . De forma predeterminada, una aplicación se pone en conversación con un contenedor y este contenedor separa los datos de esa aplicación. Esto significa que varias aplicaciones pueden almacenar información en la misma cuenta de iCloud, pero esta información nunca se entremezcha.
La contenedorización de datos de iCloud también permite a CloudKit encapsular la información del usuario. De esta manera, la aplicación tendrá acceso limitado a la cuenta de iCloud y a la información de usuario almacenada en , todo ello a la vez que se protege la privacidad y la seguridad del usuario.
Los contenedores están totalmente administrados por el desarrollador de la aplicación a través del portal de WWDR. El espacio de nombres del contenedor es global en todos los desarrolladores de Apple, por lo que el contenedor no solo debe ser único para las aplicaciones de un desarrollador determinado, sino para todos los desarrolladores y aplicaciones de Apple.
Apple sugiere usar la notación DNS inversa al crear el espacio de nombres para los contenedores de aplicaciones. Ejemplo: iCloud.com.company-name.application-name
Aunque los contenedores están, de forma predeterminada, enlazados uno a uno a una aplicación determinada, se pueden compartir entre aplicaciones. Por lo tanto, varias aplicaciones pueden coordinarse en un único contenedor. Una sola aplicación también puede hablar con varios contenedores.
Bases de datos
Una de las principales funciones de CloudKit es tomar el modelo de datos y la replicación de una aplicación que modela hasta los servidores de iCloud. Parte de la información está pensada para el usuario que la creó, otra información son datos públicos que un usuario podría crear para uso público (como una revisión de restaurante) o podría ser información que el desarrollador ha publicado para la aplicación. En cualquier caso, la audiencia no es solo un usuario, sino una comunidad de personas.
Dentro de un contenedor, primero y ante todo está la base de datos pública. Aquí es donde se encuentra toda la información pública y las co-mingles. Además, hay varias bases de datos privadas individuales para cada usuario de la aplicación.
Cuando se ejecuta en un dispositivo iOS, la aplicación solo tendrá acceso a la información del usuario de iCloud que ha iniciado sesión actualmente. Por lo tanto, la vista del contenedor de la aplicación será la siguiente:
Solo puede ver la base de datos pública y la privada asociadas al usuario de iCloud que ha iniciado sesión actualmente.
Las bases de datos se exponen en CloudKit Framework a través de la CKDatabase clase . Cada aplicación tiene acceso a dos bases de datos: la base de datos pública y la privada.
El contenedor es el punto de entrada inicial en CloudKit. El código siguiente se puede usar para acceder a la base de datos pública y privada desde el contenedor predeterminado de la aplicación:
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;
Estas son las diferencias entre los tipos de base de datos:
| Base de datos pública | Base de datos privada | |
|---|---|---|
| Tipo de datos | Datos compartidos | Datos del usuario actual |
| Cuota | Se tiene en cuenta en la cuota del desarrollador | Se tiene en cuenta en la cuota del usuario |
| Permisos predeterminados | World Readable | Legible por el usuario |
| Edición de permisos | Roles de panel de iCloud a través de un nivel de clase de registro | N/D |
Registros
Los contenedores tienen bases de datos y dentro de las bases de datos hay registros. Los registros son el mecanismo en el que los datos estructurados se mueven hacia y desde CloudKit:
Los registros se exponen en CloudKit Framework a través de CKRecord la clase , que encapsula los pares clave-valor. Una instancia de un objeto en una aplicación es equivalente a en CKRecord CloudKit. Además, cada CKRecord posee un tipo de registro, que es equivalente a la clase de un objeto .
Los registros tienen un esquema Just-In-Time, por lo que los datos se describen en CloudKit antes de entregarse para su procesamiento. A partir de ese momento, CloudKit interpretará la información y controlará la logística de almacenamiento y recuperación del registro.
La CKRecord clase también admite una amplia gama de metadatos. Por ejemplo, un registro contiene información sobre cuándo se creó y el usuario que lo creó. Un registro también contiene información sobre cuándo se modificó por última vez y el usuario que lo modificó.
Los registros contienen la noción de una etiqueta de cambio. Se trata de una versión anterior de una revisión de un registro determinado. La etiqueta change se usa como una forma ligera de determinar si el cliente y el servidor tienen la misma versión de un registro determinado.
Como se indicó anteriormente, encapsular pares clave-valor y, como tal, los siguientes tipos de datos se CKRecords pueden almacenar en un registro:
NSStringNSNumberNSDataNSDateCLLocationCKReferencesCKAssets
Además de los tipos de valor único, un registro puede contener una matriz homogéneo de cualquiera de los tipos enumerados anteriormente.
El código siguiente se puede usar para crear un registro y almacenarlo en una base de datos:
using CloudKit;
//...
private const string ReferenceItemRecordName = "ReferenceItems";
//...
var newRecord = new CKRecord (ReferenceItemRecordName);
newRecord ["name"] = (NSString)nameTextField.Text;
await CloudManager.SaveAsync (newRecord);
Zonas de registro
Los registros no existen por sí mismos dentro de una base de datos determinada: los grupos de registros existen juntos dentro de una zona de registros. Las zonas de registro se pueden pensar como tablas en bases de datos relacionales tradicionales:
Puede haber varios registros dentro de una zona de registro determinada y varias zonas de registro dentro de una base de datos determinada. Cada base de datos contiene una zona de registro predeterminada:
Aquí es donde se almacenan los registros de forma predeterminada. Además, se pueden crear zonas de registro personalizadas. Las zonas de registro representan la granularidad base en la que se realizan las confirmaciones atómicas Change Tracking datos.
Identificadores de registro
Los identificadores de registro se representan como una tupla, que contiene un nombre de registro proporcionado por el cliente y la zona en la que existe el registro. Los identificadores de registro tienen las siguientes características:
- Los crea la aplicación cliente.
- Están totalmente normalizados y representan la ubicación específica del registro.
- Al asignar el identificador único de un registro de una base de datos externa al nombre del registro, se pueden usar para establecer un puente entre bases de datos locales que no están almacenadas en CloudKit.
Cuando los desarrolladores crean nuevos registros, pueden elegir pasar un identificador de registro. Si no se especifica un identificador de registro, se creará y asignará automáticamente un UUID al registro.
Cuando los desarrolladores crean nuevos identificadores de registro, pueden elegir especificar la zona de registro a la que pertenecerá cada registro. Si no se especifica ninguno, se usará la zona de registro predeterminada.
Los identificadores de registro se exponen en CloudKit Framework a través de la CKRecordID clase . El código siguiente se puede usar para crear un nuevo identificador de registro:
var recordID = new CKRecordID("My Record");
Referencias
Las referencias proporcionan relaciones entre los registros relacionados dentro de una base de datos determinada:
En el ejemplo anterior, Los elementos primarios poseen elementos secundarios para que el elemento secundario sea un registro secundario del registro primario. La relación va del registro secundario al registro primario y se conoce como referencia atrás.
Las referencias se exponen en CloudKit Framework a través de la CKReference clase . Son una manera de permitir que el servidor de iCloud comprenda la relación entre los registros.
Las referencias proporcionan el mecanismo detrás de las eliminaciones en cascada. Si se elimina un registro primario de la base de datos, los registros secundarios (como se especifica en una relación) también se eliminarán automáticamente de la base de datos.
Nota:
Los punteros de dangling son una posibilidad al usar CloudKit. Por ejemplo, cuando la aplicación ha obtenido una lista de punteros de registro, ha seleccionado un registro y, a continuación, ha solicitado el registro, es posible que el registro ya no exista en la base de datos. Se debe codificar una aplicación para controlar esta situación correctamente.
Aunque no es necesario, se prefieren las referencias atrás al trabajar con CloudKit Framework. Apple ha ajustado el sistema para que sea el tipo de referencia más eficaz.
Al crear una referencia, el desarrollador puede proporcionar un registro que ya está en memoria o crear una referencia a un identificador de registro. Si usara un identificador de registro y la referencia especificada no existiera en la base de datos, se crearía un puntero dangling.
A continuación se muestra un ejemplo de creación de una referencia en un registro conocido:
var reference = new CKReference(newRecord, new CKReferenceAction());
Recursos
Los recursos permiten cargar un archivo de datos grandes y no estructurados en iCloud y asociarse a un registro determinado:
En el cliente, se crea un objeto que describe el archivo que se va a CKRecord cargar en el servidor de iCloud. Se CKAsset crea un objeto para contener el archivo y está vinculado al registro que lo describe.
Cuando el archivo se carga en el servidor, el registro se coloca en la base de datos y el archivo se copia en una base de datos de Storage masiva especial. Se crea un vínculo entre el puntero de registro y el archivo cargado.
Los recursos se exponen en CloudKit Framework a través de la clase y se usan para almacenar datos grandes CKAsset y no estructurados. Dado que el desarrollador nunca quiere tener datos grandes y no estructurados en la memoria, los recursos se implementan mediante archivos en disco.
Los recursos pertenecen a registros, lo que permite recuperar los recursos de iCloud mediante el registro como puntero. De este modo, el servidor puede recopilar recursos de recolección de elementos no utilizados cuando se elimina el registro que posee el recurso.
Dado CKAssets que están diseñados para administrar archivos de datos de gran tamaño, Apple diseñó CloudKit para cargar y descargar los recursos de forma eficaz.
El código siguiente se puede usar para crear un recurso y asociarlo al registro:
var fileUrl = new NSUrl("LargeFile.mov");
var asset = new CKAsset(fileUrl);
newRecord ["name"] = asset;
Ahora hemos cubierto todos los objetos fundamentales en CloudKit. Los contenedores están asociados a las aplicaciones y contienen bases de datos. Las bases de datos contienen registros que se agrupan en zonas de registro y a los que apuntan los identificadores de registro. Las relaciones de elementos primarios y secundarios se definen entre registros mediante referencias. Por último, los archivos grandes se pueden cargar y asociar a registros mediante recursos.
API de conveniencia de CloudKit
Apple ofrece dos conjuntos de API diferentes para trabajar con CloudKit:
- API operativa: ofrece todas las características de CloudKit. Para aplicaciones más complejas, esta API proporciona un control por completo sobre CloudKit.
- API de conveniencia: ofrece un subconjunto común y preconfigurado de características de CloudKit. Proporciona una solución de acceso fácil y cómoda para incluir la funcionalidad CloudKit en una aplicación iOS.
La API convenience suele ser la mejor opción para la mayoría de las aplicaciones iOS y Apple sugiere empezar por ella. En el resto de esta sección se tratarán los siguientes temas de la API convenience:
- Guardar un registro.
- Capturar un registro.
- Actualizar un registro.
Código de instalación común
Antes de empezar a trabajar con la API De conveniencia de CloudKit, se requiere algún código de instalación estándar. Para empezar, modifique el archivo de AppDelegate.cs la aplicación y haga que sea parecido al siguiente:
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");
}
}
}
El código anterior expone las bases de datos cloudKit públicas y privadas como accesos directos para facilitar su trabajo en el resto de la aplicación.
A continuación, agregue el código siguiente a cualquier contenedor de vistas o vistas que use CloudKit:
using CloudKit;
//...
public AppDelegate ThisApp {
get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
}
Esto agrega un acceso directo para obtener acceso a y acceder a los accesos directos de base de datos AppDelegate públicos y privados creados anteriormente.
Con este código implementado, echemos un vistazo a la implementación de cloudkit Convenience API en una aplicación xamarin iOS 8.
Guardar un registro
Con el patrón presentado anteriormente al analizar Registros, el código siguiente creará un nuevo registro y usará la API Convenience para guardarlo en la base de datos pública:
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) {
...
}
});
Tres aspectos que debe tener en cuenta sobre el código anterior:
- Al llamar al método de , el desarrollador no tiene que especificar cómo se envían los datos, en qué zona se
SaveRecordPublicDatabaseescriben, etc. La API convenience se encarga de todos esos detalles. - La llamada es asincrónica y proporciona una rutina de devolución de llamada cuando se completa la llamada, ya sea con éxito o con error. Si se produce un error en la llamada, se proporciona un mensaje de error.
- CloudKit no proporciona almacenamiento ni persistencia locales; solo es un medio de transferencia. Por lo tanto, cuando se realiza una solicitud para guardar un registro, se envía inmediatamente a los servidores de iCloud.
Nota:
Debido a la naturaleza "perdida" de las comunicaciones de red móvil, donde las conexiones se descartan o interrumpen constantemente, una de las primeras consideraciones que debe tener en cuenta el desarrollador al trabajar con CloudKit es el control de errores.
Captura de un registro
Con un registro creado y almacenado correctamente en el servidor de iCloud, use el código siguiente para recuperar el registro:
// 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) {
...
}
});
Al igual que al guardar el registro, el código anterior es asincrónico, sencillo y requiere un excelente control de errores.
Actualizar un registro
Una vez que se ha obtenido un registro de los servidores de iCloud, se puede usar el código siguiente para modificar el registro y guardar los cambios en la base de datos:
// 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) {
...
}
});
}
});
El FetchRecord método de devuelve si la llamada se ha realizado PublicDatabaseCKRecord correctamente. A continuación, la aplicación modifica el registro y llama de SaveRecord nuevo a para volver a escribir los cambios en la base de datos.
En esta sección se ha mostrado el ciclo típico que usará una aplicación al trabajar con la API De conveniencia de CloudKit. La aplicación guardará Registros en iCloud, recuperará esos registros de iCloud, modificará los registros y guardará esos cambios en iCloud.
Diseño para la escalabilidad
Hasta ahora, en este artículo se ha visto cómo almacenar y recuperar todo el modelo de objetos de una aplicación desde los servidores de iCloud, cada vez que se va a trabajar con él. Aunque este enfoque funciona bien con una pequeña cantidad de datos y una base de usuarios muy pequeña, no se escala bien cuando aumenta la cantidad de información o la base de usuarios.
Big data, tiny device
Entre más popular sea una aplicación, más datos de la base de datos y menos factible será tener una caché de todos los datos en el dispositivo. Se pueden usar las técnicas siguientes para resolver este problema:
- Mantener los datos grandes en la nube: CloudKit se diseñó para controlar datos grandes de forma eficaz.
- El cliente solo debe ver un segmento de los datos: se debe bajar el mínimo de datos necesario para controlar cualquier tarea en un momento dado.
- Las vistas de cliente pueden cambiar: dado que cada usuario tiene preferencias diferentes, el segmento de datos que se muestra puede cambiar de usuario a usuario y la vista individual del usuario de cualquier segmento determinado puede ser diferente.
- El cliente usa consultas para centrar el punto de vista: las consultas permiten al usuario ver un pequeño subconjunto de un conjunto de datos mayor que existe en la nube.
Consultas
Como se indicó anteriormente, las consultas permiten al desarrollador seleccionar un pequeño subconjunto del conjunto de datos más grande que existe en la nube. Las consultas se exponen en CloudKit Framework a través de la CKQuery clase .
Una consulta combina tres cosas diferentes: un tipo de registro ( ), un RecordType predicado ( ) y, opcionalmente, un NSPredicate descriptor de ordenación ( NSSortDescriptors ). CloudKit admite la mayoría de NSPredicate .
Predicados admitidos
CloudKit admite los siguientes tipos de NSPredicates al trabajar con consultas:
Registros de coincidencia donde el nombre es igual a un valor almacenado en una variable:
NSPredicate.FromFormat(string.Format("name = '{0}'", recordName))Permite que la coincidencia se base en un valor de clave dinámica, de modo que la clave no tenga que conocerse en tiempo de compilación:
NSPredicate.FromFormat(string.Format("{0} = '{1}'", key, value))Registros de coincidencia donde el valor del registro es mayor que el valor especificado:
NSPredicate.FromFormat(string.Format("start > {0}", (NSDate)date))Registros de coincidencia en los que la ubicación del registro está a menos de 100 metros de la ubicación especificada:
var location = new CLLocation(37.783,-122.404); var predicate = NSPredicate.FromFormat(string.Format("distanceToLocation:fromLocation(Location,{0}) < 100", location));CloudKit admite una búsqueda con tokens. Esta llamada creará dos tokens, uno para
aftery otro parasession. Devolverá un registro que contiene esos dos tokens:NSPredicate.FromFormat(string.Format("ALL tokenize({0}, 'Cdl') IN allTokens", "after session"))CloudKit admite predicados compuestos unidos mediante el
ANDoperador .NSPredicate.FromFormat(string.Format("start > {0} AND name = '{1}'", (NSDate)date, recordName))
Creación de consultas
El código siguiente se puede usar para crear un CKQuery en una aplicación de Xamarin iOS 8:
var recordName = "MyRec";
var predicate = NSPredicate.FromFormat(string.Format("name = '{0}'", recordName));
var query = new CKQuery("CloudRecords", predicate);
En primer lugar, crea un predicado para seleccionar solo los registros que coinciden con un nombre determinado. A continuación, crea una consulta que seleccionará registros del tipo de registro especificado que coinciden con el predicado.
Realización de una consulta
Una vez creada una consulta, use el código siguiente para realizar la consulta y procesar los registros devueltos:
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];
}
}
});
El código anterior toma la consulta creada anteriormente y la ejecuta en la base de datos pública. Puesto que no se especifica ninguna zona de registro, se busca en todas las zonas. Si no se ha producido ningún error, se devolverá una matriz de que CKRecords coincida con los parámetros de la consulta.
La manera de pensar en las consultas es que son sondeos y son excelentes para la selección a través de grandes conjuntos de datos. Sin embargo, las consultas no son adecuadas para conjuntos de datos grandes, principalmente estáticos, debido a las razones siguientes:
- Son malo para la duración de la batería del dispositivo.
- Son mal para el tráfico de red.
- No son correctas para la experiencia del usuario porque la información que ven está limitada por la frecuencia con la que la aplicación sondear la base de datos. Actualmente, los usuarios esperan notificaciones push cuando algo cambia.
Suscripciones
Cuando se trabaja con grandes conjuntos de datos, principalmente estáticos, la consulta no debe realizarse en el dispositivo cliente, debe ejecutarse en el servidor en nombre del cliente. La consulta debe ejecutarse en segundo plano y debe ejecutarse después de cada único registro guardado, ya sea por el dispositivo actual u otro dispositivo que toque la misma base de datos.
Por último, se debe enviar una notificación push a todos los dispositivos conectados a la base de datos cuando se ejecuta la consulta del lado servidor.
Las suscripciones se exponen en CloudKit Framework a través de la CKSubscription clase . Combinan un tipo de registro ( RecordType ), un predicado ( ) y una notificación push de Apple ( NSPredicatePush ).
Nota:
Las inserciones de CloudKit se aumentan ligeramente, ya que contienen una carga que contiene información específica de CloudKit, como la causa de la inserción.
Cómo funcionan las suscripciones
Antes de implementar la suscripción en código de C#, veamos una introducción rápida sobre cómo funcionan las suscripciones:
En el gráfico anterior se muestra el proceso de suscripción típico de la siguiente manera:
- El dispositivo cliente crea una nueva suscripción que contiene el conjunto de condiciones que desencadenarán la suscripción y una notificación push que se enviará cuando se produzca el desencadenador.
- La suscripción se envía a la base de datos donde se agrega a la colección de suscripciones existentes.
- Un segundo dispositivo crea un nuevo registro y lo guarda en la base de datos.
- La base de datos busca en su lista de suscripciones para ver si el nuevo registro coincide con cualquiera de sus condiciones.
- Si se encuentra una coincidencia, la notificación push se envía al dispositivo que registró la suscripción con información sobre el registro que hizo que se desencadenara.
Con estos conocimientos, echemos un vistazo a la creación de suscripciones en una aplicación xamarin iOS 8.
Creación de suscripciones
El código siguiente se puede usar para crear una suscripción:
// 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;
En primer lugar, crea un predicado que proporciona la condición para desencadenar la suscripción. A continuación, crea la suscripción con un tipo de registro específico y establece la opción de cuando se prueba el desencadenador. Por último, define el tipo de notificación que se producirá cuando se desencadene la suscripción y la adjunte a la suscripción.
Guardar suscripciones
Con la suscripción creada, el código siguiente la guardará en la base de datos:
// Save the subscription to the database
ThisApp.PublicDatabase.SaveSubscription(subscription, (s, err) => {
// Was there an error?
if (err != null) {
}
});
Con la API Convenience, la llamada es asincrónica, sencilla y proporciona un fácil control de errores.
Control de notificaciones push
Si el desarrollador ha usado anteriormente notificaciones push de Apple (APS), el proceso de tratar las notificaciones generadas por CloudKit debe ser familiar.
En AppDelegate.cs , invalide ReceivedRemoteNotification la clase como se muestra a continuación:
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;
}
}
El código anterior pide a CloudKit que analice userInfo en una notificación de CloudKit. A continuación, se extrae información sobre la alerta. Por último, se prueba el tipo de notificación y la notificación se controla en consecuencia.
En esta sección se ha mostrado cómo responder al problema de big data, tiny device presentado anteriormente mediante consultas y suscripciones. La aplicación dejará sus datos grandes en la nube y usará estas tecnologías para proporcionar vistas a este conjunto de datos.
Cuentas de usuario de CloudKit
Como se indicó al principio de este artículo, CloudKit se basa en la infraestructura de iCloud existente. En la sección siguiente se trata, en detalle, cómo se exponen las cuentas a un desarrollador mediante la API de CloudKit.
Autenticación
Cuando se trabaja con cuentas de usuario, la primera consideración es la autenticación. CloudKit admite la autenticación a través del usuario de iCloud que ha iniciado sesión actualmente en el dispositivo. La autenticación tiene lugar en segundo plano y se controla mediante iOS. De esta manera, los desarrolladores nunca tienen que preocuparse por los detalles de la implementación de la autenticación. Solo prueban para ver si un usuario ha iniciado sesión.
Información de cuenta de usuario
CloudKit proporciona la siguiente información de usuario al desarrollador:
- Identidad: una manera de identificar de forma única al usuario.
- Metadatos: la capacidad de guardar y recuperar información sobre los usuarios.
- Privacidad: toda la información se controla en un ambiente consciente de la privacidad. No se expone nada a menos que el usuario lo haya aceptado.
- Detección: ofrece a los usuarios la capacidad de detectar a sus amigos que usan la misma aplicación.
A continuación, se verán estos temas en detalle.
Identidad
Como se indicó anteriormente, CloudKit proporciona una manera de que la aplicación identifique de forma única a un usuario determinado:
Hay una aplicación cliente que se ejecuta en los dispositivos de un usuario y en todas las bases de datos privadas de usuario específicas dentro del contenedor de CloudKit. La aplicación cliente se va a vincular a uno de esos usuarios específicos. Esto se basa en el usuario que ha iniciado sesión en iCloud localmente en el dispositivo.
Dado que esto es procedente de iCloud, hay un amplio almacén de respaldo de información de usuario. Y dado que iCloud hospeda realmente el contenedor, puede poner en correlación a los usuarios. En el gráfico anterior, el usuario cuya cuenta de iCloud user@icloud.com está vinculada al cliente actual.
En un contenedor por contenedor, se crea un identificador de usuario único generado aleatoriamente y se asocia a la cuenta de iCloud del usuario (dirección de correo electrónico). Este identificador de usuario se devuelve a la aplicación y se puede usar de la manera que el desarrollador lo vea oportuno.
Nota:
Las distintas aplicaciones que se ejecutan en el mismo dispositivo para el mismo usuario de iCloud tendrán distintos id. de usuario porque están conectadas a diferentes contenedores de CloudKit.
El código siguiente obtiene el identificador de usuario de CloudKit para el usuario de iCloud que ha iniciado sesión actualmente en el dispositivo:
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;
}
});
El código anterior pide al contenedor de CloudKit que proporcione el identificador del usuario que ha iniciado sesión actualmente. Dado que esta información viene de iCloud Server, la llamada es asincrónica y se requiere el control de errores.
Metadatos
Cada usuario de CloudKit tiene metadatos específicos que los describen. Estos metadatos se representan como un registro de CloudKit:
Si busca en la base de datos privada un usuario específico de un contenedor, hay un registro que define ese usuario. Hay muchos registros de usuario dentro de la base de datos pública, uno para cada usuario del contenedor. Una de ellas tendrá un identificador de registro que coincida con el identificador de registro del usuario que ha iniciado sesión actualmente.
Los registros de usuario de la base de datos pública son legibles en todo el mundo. Se tratan, en su mayor parte, como un registro normal y tienen un tipo de CKRecordTypeUserRecord . El sistema reserva estos registros y no están disponibles para las consultas.
Use el código siguiente para acceder a un registro de usuario:
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;
}
});
El código anterior pide a la base de datos pública que devuelva el registro de usuario del usuario al que se ha accedido anteriormente. Dado que esta información viene de iCloud Server, la llamada es asincrónica y se requiere el control de errores.
Privacidad
CloudKit se diseñó, de forma predeterminada, para proteger la privacidad del usuario que ha iniciado sesión actualmente. De forma predeterminada, no se expone ninguna información de identificación personal sobre el usuario. Hay algunos casos en los que la aplicación requerirá información limitada sobre el usuario.
En estos casos, la aplicación puede solicitar que el usuario divulgue esta información. Se mostrará un cuadro de diálogo al usuario en el que se le pedirá que opte por exponer la información de su cuenta.
Detección
Suponiendo que el usuario ha optado por permitir que la aplicación limite el acceso a la información de su cuenta de usuario, puede ser reconocible para otros usuarios de la aplicación:
La aplicación cliente está hablando con un contenedor y el contenedor está hablando con iCloud para acceder a la información del usuario. El usuario puede proporcionar una dirección de correo electrónico y la detección se puede usar para obtener información sobre el usuario. Opcionalmente, el identificador de usuario también se puede usar para detectar información sobre el usuario.
CloudKit también proporciona una manera de detectar información sobre cualquier usuario que pueda ser amigos del usuario de iCloud que ha iniciado sesión actualmente consultando toda la libreta de direcciones. El proceso de CloudKit extraerá el libro de contactos del usuario y usará las direcciones de correo electrónico para ver si puede encontrar otras de la aplicación que coincidan con esas direcciones.
Esto permite a la aplicación aprovechar el libro de contactos del usuario sin proporcionar acceso a él ni pedir al usuario que apruebe el acceso a los contactos. En ningún momento la información de contacto está disponible para la aplicación, solo el proceso de CloudKit tiene acceso.
Como resumen, hay tres tipos diferentes de entradas disponibles para la detección de usuarios:
- Identificador de registro de usuario: la detección se puede realizar con el identificador de usuario del usuario que ha iniciado sesión actualmente en CloudKit.
- Dirección de correo electrónico del usuario: el usuario puede proporcionar una dirección de correo electrónico y se puede usar para la detección.
- Libro de contactos: la libreta de direcciones del usuario se puede usar para detectar usuarios de la aplicación que tienen la misma dirección de correo electrónico que aparecen en sus contactos.
La detección de usuarios devolverá la siguiente información:
- Id. de registro de usuario: identificador único de un usuario en la base de datos pública.
- Nombre y apellidos: tal y como se almacena en la base de datos pública.
Esta información solo se devolverá para los usuarios que han optado por la detección.
El código siguiente detectará información sobre el usuario que ha iniciado sesión actualmente en iCloud en el dispositivo:
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;
}
});
Use el código siguiente para consultar a todos los usuarios en el libro de contactos:
// 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];
}
}
});
En esta sección hemos abordado las cuatro áreas principales de acceso a la cuenta de un usuario que CloudKit puede proporcionar a una aplicación. Desde obtener la identidad y los metadatos del usuario, hasta las directivas de privacidad integradas en CloudKit y, por último, la capacidad de detectar otros usuarios de la aplicación.
Los entornos de desarrollo y producción
CloudKit proporciona entornos de desarrollo y producción independientes para los tipos de registro y los datos de una aplicación. El entorno de desarrollo es un entorno más flexible que solo está disponible para los miembros de un equipo de desarrollo. Cuando una aplicación agrega un nuevo campo a un registro y guarda ese registro en el entorno de desarrollo, el servidor actualiza automáticamente la información del esquema.
El desarrollador puede usar esta característica para realizar cambios en un esquema durante el desarrollo, lo que ahorra tiempo. Una advertencia es que después de agregar un campo a un registro, el tipo de datos asociado a ese campo no se puede cambiar mediante programación. Para cambiar el tipo de un campo, el desarrollador debe eliminar el campo en el panel de CloudKit y agregarlo de nuevo con el nuevo tipo.
Antes de implementar la aplicación, el desarrollador puede migrar su esquema y sus datos al entorno de producción mediante el panel de CloudKit. Cuando se ejecuta en el entorno de producción, el servidor impide que una aplicación cambie el esquema mediante programación. El desarrollador todavía puede realizar cambios con el panel de CloudKit, pero los intentos de agregar campos a un registro en el entorno de producción producen errores.
Nota:
El simulador de iOS solo funciona con el entorno de desarrollo. Cuando el desarrollador está listo para probar una aplicación en un entorno de producción,se requiere un dispositivo iOS físico.
Envío de una aplicación habilitada para CloudKit
Antes de enviar una aplicación que usa CloudKit, deberá configurarse para que tenga como destino el entorno de CloudKit de producción o Apple rechazará la aplicación.
Haga lo siguiente:
En Visual Studio ma, compile la aplicación pararelease iOS Device:
En el menú Compilar, seleccione Archivar:
El archivo se creará y se mostrará en Visual Studio para Mac:
Inicie Xcode.
En el menú Ventana, seleccione Organizador:
Seleccione el archivo de la aplicación y haga clic en el botón Exportar...:
Seleccione un método para exportar y haga clic en el botón Siguiente:
Seleccione el equipo de desarrollo en la lista desplegable y haga clic en el botón Elegir:
Seleccione Producción en la lista desplegable y haga clic en el botón Siguiente:
Revise la configuración y haga clic en el botón Exportar:
Elija una ubicación para generar el archivo de aplicación
.iparesultante.
El proceso es similar para enviar la aplicación directamente a iTunes Conectar, simplemente haga clic en el botón Enviar... en lugar de exportar... después de seleccionar un archivo en la ventana Organizador.
Cuándo usar CloudKit
Como hemos visto en este artículo, CloudKit proporciona una manera sencilla de que una aplicación almacene y recupere información de los servidores de iCloud. Dicho esto, CloudKit no deja obsoleta ni desusa ninguna de las herramientas o marcos existentes.
Casos de uso
Los siguientes casos de uso deben ayudar al desarrollador a decidir cuándo usar una tecnología o un marco de iCloud específicos:
- iCloud Key-Value Store: mantiene actualizada una pequeña cantidad de datos de forma asincrónica y es excelente para trabajar con las preferencias de la aplicación. Sin embargo, está restringida para una cantidad muy pequeña de información.
- iCloud Drive: se basa en las API de documentos de iCloud existentes y proporciona una API sencilla para sincronizar datos no estructurados desde el sistema de archivos. Proporciona una caché sin conexión completa en Mac OS X y es excelente para aplicaciones centradas en documentos.
- Datos principales de iCloud: permite replicar datos entre todos los dispositivos del usuario. Los datos son de un solo usuario y son excelentes para mantener sincronizados los datos privados y estructurados.
- CloudKit: proporciona datos públicos tanto de estructura como de forma masiva, y es capaz de controlar tanto grandes conjuntos de datos como archivos no estructurados de gran tamaño. Está vinculado a la cuenta de iCloud del usuario y proporciona transferencia de datos dirigida por el cliente.
Teniendo en cuenta estos casos de uso, el desarrollador debe elegir la tecnología correcta de iCloud para proporcionar la funcionalidad de aplicación necesaria actual y proporcionar una buena escalabilidad para el crecimiento futuro.
Resumen
En este artículo se ha abordado una introducción rápida a cloudkit API. Se ha mostrado cómo aprovisionar y configurar una aplicación de Xamarin iOS para usar CloudKit. Ha cubierto las características de cloudKit Convenience API. Muestra cómo diseñar una aplicación habilitada para CloudKit para la escalabilidad mediante consultas y suscripciones. Por último, ha mostrado la información de la cuenta de usuario que CloudKit expone a una aplicación.





















