Krypton Solid

Poner en práctica el back-end móvil como servicio (Parte 1)

Poner en práctica el back-end móvil como servicio (Parte 1)

En un artículo anterior, presenté el back-end móvil como servicio (MBaaS) que tiene como objetivo brindar a los desarrolladores de aplicaciones la capacidad de crear aplicaciones nativas y web multiplataforma completas con nuevas funciones sin problemas.

El siguiente paso es implementar una aplicación de demostración completa usando esas ideas. A través de esta aplicación de trabajo real, podrá ver las áreas en las que MBaaS aporta valor. Esta primera parte lo guiará a través de una demostración de la aplicación de mensajería impulsada por la aplicación Kinvey y explorará cómo aprovechar la administración de usuarios, el almacenamiento de archivos y el almacenamiento de datos.

Otras lecturas en SmashingMag

La segunda parte completará la demostración y demostrará cómo aprovechar dos piezas clave de la funcionalidad de Kinvey: los permisos proporcionados por el almacén de datos y las notificaciones automáticas, que se habilitan a través de la funcionalidad de lógica empresarial.

Configuración

Antes de saltar a la aplicación de demostración, quiero resaltar algunos puntos. Primero, debido a que estoy usando una aplicación real para discutir MBaaS, el conocimiento de la plataforma de desarrollo sería extremadamente útil. Estoy aprovechando iOS con Swift. Además, saber cómo integrarse con los servicios de back-end sin duda sería útil para comprender más sobre lo que Kinvey está haciendo bajo el capó. Si bien todo esto es útil, se incluye el código fuente completo de la aplicación; no dude en analizar el código a su propio ritmo.

En segundo lugar, debido a que la aplicación de demostración tiene más un enfoque empresarial (en lugar de un enfoque al consumidor), elegí Kinvey para la plataforma MBaaS. En el último artículo, analicé el proceso de evaluación de proveedores de MBaaS. Tenga en cuenta que Kinvey no es un servicio gratuito y los términos de licencia se adjuntan a sus SDK (como era de esperar). Los términos de licencia se incluyen con cada descarga de SDK. Puede obtener más información en los siguientes enlaces:

Una aplicación de demostración

En los últimos tres años, varios clientes se me acercaron para desarrollar una plataforma de mensajería interna para su organización. Esta necesidad ha llevado al éxito de empresas como Flojo (que usamos internamente en Mente universal) y otros similares. Debido a que esta era una solicitud común, quería ver qué se necesitaría para implementar una solución básica de mensajería uno a uno para una organización por encima de una solución MBaaS.

Para ayudarlo a comprender estos conceptos en una aplicación real, proporcioné el código fuente completo de la aplicación. Puedes comprobarlo en Github, «Demostración de WaterCooler. «

Nota: Para obtener más información sobre cómo elegir entre las opciones de MBaaS disponibles, consulte el artículo inicial de esta serie, «Comprensión del back-end móvil como servicio».

Aplicación de mensajería de demostración WaterCooler. (Ver versión grande)

Resumen de requisitos

Para ilustrar cómo una solución MBaaS puede impulsar una aplicación como esta, debemos cumplir algunos requisitos clave. Los usuarios deberían poder hacer lo siguiente con la aplicación:

  • crear una cuenta y configurar su perfil (incluyendo nombre, título, foto de perfil, dirección de correo electrónico y contraseña);
  • inicie sesión (y se le pedirá que inicie sesión solo una vez, al menos hasta que cierre la sesión);
  • intercambiar mensajes uno a uno con otros miembros (visibles solo para el remitente y el destinatario e inaccesibles para otros usuarios);
  • navegar por un directorio de miembros que actualmente tienen una cuenta en la plataforma;
  • cerrar sesión;
  • administrar y actualizar la información de su perfil;
  • recibir una alerta mediante una notificación automática de que han recibido un nuevo mensaje.

Las siguientes secciones detallan cómo utilicé Kinvey para cumplir con estos requisitos. Si bien no entraré en detalles sobre cómo se creó cada parte de la aplicación, brindaré un contexto completo de las áreas en las que se aprovechó Kinvey.

Detalles técnicos

La aplicación de demostración es una aplicación para iOS dirigida a iOS 8+. Utiliza Swift (Xcode 6.1.1 e iOS 8.1.3).

La interfaz de usuario se creó siguiendo los principios estándar de la interfaz de usuario para iOS. Aprovecha Diseño automático (tanto dentro del guión gráfico como programáticamente). La creación de esta interfaz está más allá del alcance del artículo, pero es de esperar que el código de ejemplo sea útil para sus aplicaciones iOS.

Empezando con Kinvey

Si lo está siguiendo, probablemente querrá compilar el código fuente y ejecutar la aplicación usted mismo. Para hacer esto, necesitará crear una aplicación Kinvey e incluir las credenciales de la aplicación en su código.

Creación de una aplicación y un entorno Kinvey

Para crear una aplicación y un entorno Kinvey, deberá crear una cuenta de Kinvey. Después de registrarse, seleccione «Comenzar con su primera aplicación». En esta página, asigne un nombre a su aplicación, seleccione iOS y la plataforma, y ​​luego haga clic en «Crear aplicación».

Captura de pantalla de la creación de una aplicación en Kinvey
Una vista del proceso de creación de una aplicación en Kinvey. (Ver versión grande)

A partir de aquí, tendrá una aplicación creada con un único entorno de desarrollo. Al hacer clic en el entorno «Desarrollo», accederá a la consola. En la consola, verá tanto su appKey y appSecret en la parte superior derecha. Copie estos datos porque deberá incluirlos en la aplicación de iOS.

Configuración de la aplicación iOS

Una vez que haya creado su aplicación Kinvey y reunido sus credenciales, tome el código del repositorio. A continuación, abra el AppDelegate.swift archivar y actualizar estos valores en el application:DidFinishLaunchingWithOptions: método.

// Extracted from AppDelegate.swift (http://tuck.cc/1w7wkyI)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

 // --------------------------------------------------------------------
 // INCLUDE YOUR KINVEY CREDENTIALS HERE
 // --------------------------------------------------------------------
 let appKey = ""
 let appSecret = ""

 //---------------------------------------------------------------------
 …
}

Una vez que esté en su lugar, debería poder ejecutar la aplicación como se esperaba. Si desea ejecutar la aplicación en un dispositivo, deberá actualizar la firma de código como perfiles de aprovisionamiento (como con cualquier aplicación de iOS).

  • Para obtener más información sobre cómo configurar una aplicación iOS con Kinvey, consulte el «Empezando» tutorial.

Gestión de usuarios

Un elemento fundamental de cualquier MBaaS es la gestión de usuarios. Esta aplicación aprovechará la gestión de usuarios para controlar las cuentas de usuarios individuales y su respectiva información de perfil, además de proporcionar un directorio de todos los usuarios del sistema. Al igual que con el resto de la funcionalidad que cubriremos, esta integración se proporciona a través de Kinvey’s SDK de iOS.

Registro, inicio de sesión y vistas de perfil
Una vista de las vistas de registro, inicio de sesión y perfil en la aplicación. (Ver versión grande)

Crear un usuario

El primer paso del proceso es permitir que un usuario cree una cuenta. Cuando un usuario inicia la aplicación, aterrizará en la vista que le permite iniciar sesión o registrarse. Si el usuario selecciona «Registrarse», será llevado a la página «Registrarse», que lo guiará a través del proceso de ingresar la información de su perfil. Cuando se completa este proceso, se ejecuta el siguiente código, que crea una cuenta e inicia la sesión del usuario en la aplicación.

En este ejemplo, verá el KCSUser clase. Esta clase maneja la representación de un usuario y también es la puerta de enlace para todas las operaciones relacionadas con la gestión de usuarios:

// Extracted from SignupViewController.swift (http://tuck.cc/1vsaWcr)

// Set the parameters of the user
var userParams = [
 KCSUserAttributeGivenname : firstNameField.text,
 KCSUserAttributeSurname : lastNameField.text,
 KCSUserAttributeEmail : emailField.text,
 kWaterCoolerUserTitleValue : titleField.text
];

// Save the user to Kinvey
KCSUser.userWithUsername(emailField.text, password: passwordField.text, fieldsAndValues: userParams) { (user:KCSUser!, error:NSError!, result:KCSUserActionResult) in
 if(error != nil) {
 println("USER NOT CREATED - ERROR: " + error.description)
 } else {
 // User created successfully
 // Do other tasks, such as uploading profile picture to the file store
 }
}

En este caso, los campos de nombre, apellido y dirección de correo electrónico se incluyen en el KCSUser objeto. Sin embargo, Kinvey también nos permite guardar otros datos en este objeto. El título del usuario se guardará en uno de estos campos adicionales. Una extensión del KCSUser También se incluye el objeto (como se ve a continuación) para facilitar el acceso a este valor para un usuario dentro de la aplicación:

// Extracted from KinveyExtensions.swift (http://tuck.cc/1vsb5N7)

// Create a constant for accessing the title key from the user object
let kWaterCoolerUserTitleValue = "title"

extension KCSUser {
 var title:String {
 return self.getValueForAttribute(kWaterCoolerUserTitleValue) as String!
 }
}

Iniciando sesión

Si el usuario selecciona la opción de iniciar sesión desde la página de destino, podrá ingresar su dirección de correo electrónico y contraseña (que ingresó en el proceso de registro). Se les presenta una alerta si su intento no tiene éxito y, si inician sesión correctamente, se les redirige a la vista principal de la aplicación.

// Extracted from LandingPageViewController.swift (http://tuck.cc/1vsbeAe)

func attemptLogin() {
 // Get the values from the form
 let username = loginEmailField.text
 let password = loginPasswordField.text

 // Attempt to log in to the application
 KCSUser.loginWithUsername(username, password: password) { (user, error, actionResult) -> Void in
 if(error == nil) {
 self.successfulLogin()
 } else {
 self.incorrectLoginWithError(error)
 }
 }
}

func incorrectLoginWithError(error:NSError) {
 // Let the user know an error occurred in login. In this case
 // we just present an alert using the UIAlertController.
 let alert = UIAlertController(title: "Failed Login", message: error.localizedDescription, preferredStyle: UIAlertControllerStyle.Alert)
 alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: { (alertAction) -> Void in
 self.dismissViewControllerAnimated(true, completion:nil)
 }))

 // Present the alert
 presentViewController(alert, animated: true, completion: nil)
}

func successfulLogin() {
 // There is already a segue defined to the main threads view.
 // We need to perform this segue if we have a successful login.
 performSegueWithIdentifier(WaterCoolerConstants.Segue.Login, sender: self)
}

Saliendo de tu cuenta

Desde la página de administración de perfiles, el usuario puede cerrar la sesión de la aplicación. Al hacer esto, el SDK de iOS de Kinvey también realiza un trabajo adicional en segundo plano, incluido el borrado de los valores almacenados en caché. En este ejemplo, después de cerrar la sesión, se redirige al usuario a la página de destino.

// Perform the log-out and send the user to landing page
@IBAction func logout() {
 KCSUser.activeUser().logout()
 performSegueWithIdentifier(WaterCoolerConstants.Segue.Logout, sender: self)
}

Directorio de usuarios

Para cumplir con todos nuestros requisitos, la aplicación también debe proporcionar una lista de todos los usuarios. Una colección especial, KCSCollection.userCollection(), proporciona acceso a la colección de usuarios de una aplicación. Una vez que haya creado una tienda a partir de esta colección, puede consultarla como lo haría con cualquier otra colección de datos. El siguiente ejemplo ilustra cómo buscar todos los usuarios para la aplicación:

// Extracted from KinveyDataManager.swift (http://tuck.cc/1vsd0Bp)

// Create the app data store corresponding to the users collection
lazy var userStore:KCSAppdataStore = {
 let userCollection:KCSCollection = KCSCollection.userCollection()
 let store = KCSAppdataStore(collection: userCollection, options: nil)
 return store
}()

// Fetch the users from the user store
func fetchUsers(completion: ([KCSUser]!, NSError!) -> ()) {
 userStore.queryWithQuery(KCSQuery(), withCompletionBlock: { (results, error) -> Void in
 if(error == nil) {
 self.users = results as [KCSUser]
 completion(results as [KCSUser]!, nil)
 } else {
 completion(nil, error)
 }
 }, withProgressBlock: nil)
}

Nota: Para obtener más información sobre la administración de usuarios con el SDK de iOS de Kinvey, asegúrese de consultar el «Usuarios» guía.

Gestión de archivos

Una característica poderosa de muchas soluciones MBaaS es el almacenamiento de archivos. En nuestra aplicación WaterCooler, esto entra en juego cuando un usuario crea una cuenta y agrega una imagen de perfil. También podríamos aprovechar esto en gran medida para ampliar la aplicación para admitir la carga de imágenes dentro de los mensajes. En este proceso, el archivo se carga en una red de entrega de contenido (CDN) y, como cualquier otro dato, tiene una configuración completa de permisos.

// Extracted from SignupViewController.swift (http://tuck.cc/1vsaWcr)

// Upload the profile picture to the Kinvey file store
func uploadProfilePicture(completion:(file:KCSFile!) -> ()) {
 if((self.photo.image) != nil) {
 let photoData = UIImageJPEGRepresentation(self.photo.image, 1.0)

 KCSFileStore.uploadData(photoData, options: fileParams, completionBlock: { (file:KCSFile!, error:NSError!) -> Void in
 completion(file: file);
 }, progressBlock: nil);

 } else {
 completion(file: nil);
 }
}

// Once we have completed the file upload, assign the file ID to the user
// using a custom attribute
func assignProfilePictureIdToUser(user:KCSUser, picture:KCSFile, completion: () -> Void) {
 user.setValue(picture.kinveyObjectId(), forAttribute: kWaterCoolerUserProfilePicFileId);
 user.saveWithCompletionBlock { (user:[AnyObject]!, error:NSError!) -> Void in
 completion();
 }
}

En el código anterior, se producen dos pasos distintos. Primero, estamos cargando la foto de perfil en el almacén de archivos. Una vez que se completa este proceso, estamos actualizando al usuario con el ID que ha devuelto el almacén de archivos. De esta manera, estamos aprovechando otra propiedad personalizada del usuario para almacenar una información de identificación. Ahora, en cualquier lugar que muestre una lista de usuarios, también podemos mostrar su foto de perfil.

Nota: Para obtener más información sobre cómo trabajar con archivos en el SDK de iOS de Kinvey, consulte la sección «Archivos» guía.

Modelo de datos

Uno de los beneficios del SDK de iOS de Kinvey es que le permite mapear sus objetos Swift (u Objective-C) a los objetos de la colección Kinvey. La KCSUser class es una clase especial que ya está definida y asignada al objeto de usuario, pero en nuestro caso crearemos dos clases de datos adicionales que se asignan a las conversaciones y los mensajes dentro de ellas.

Modelo de datos de WaterCooler

El modelo de datos de WaterCooler tendrá dos entidades principales, Message y MessageThread.

La MessageThread La clase se encargará de representar una conversación entre dos usuarios. Contendrá información sobre los usuarios involucrados en la conversación, así como una referencia al último mensaje enviado en la conversación.

Dentro de Kinvey, el entityId es un campo especial. Si no le asigna un valor, el sistema le asignará uno cuando el objeto se guarde en el almacén de datos. En nuestro caso, seguiremos adelante y definiremos un valor especial que se asigna a los dos usuarios que están en una conversación para el MessageThread clase. El método que calcula este valor se puede ver a continuación:

// Extracted from MessageThread.swift (http://tuck.cc/1w7jdOd)

// This method simply takes a user and the current user and creates
// an ID based on the alphabetized array of user IDs between these
// two users. In this way, we don't have to fetch additional information
// when displaying the message thread view.
class func threadIdentifierForUser(user:KCSUser) -> String {
 let userAIdentifier:String = KCSUser.activeUser().userId
 let userBIdentifier:String = user.userId
 let identifiers:[String] = [ userAIdentifier, userBIdentifier ]
 let sortedIdentifiers = identifiers.sorted {
 $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending
 }
 return ":".join(sortedIdentifiers)
}

La Message la clase será responsable de rastrear un mensaje individual dentro de una conversación general. Esta clase contiene información sobre el mensaje, incluida la hora, el contenido, el remitente y el hilo de mensajes relacionado. Para obtener todos los mensajes de una conversación en particular, simplemente consultamos en función de la threadId de la conversación. El siguiente código recupera todos los mensajes de un hilo de mensajes predefinido:

// Extracted from KinveyDataManager.swift (http://tuck.cc/1vsd0Bp)

func messagesForThread(thread:MessageThread, completion:([Message]) -> ()) {
 let query = KCSQuery(onField: "threadId", withExactMatchForValue: thread.entityId)
 messagesStore.queryWithQuery(query, withCompletionBlock: { (results, error) -> Void in
 completion(results as [Message])
 }, withProgressBlock: nil)
}

Relaciones del modelo de datos

Kinvey admite relaciones de modelos de datos tanto en el almacén de datos principal como en el SDK de iOS. En nuestra situación, el lastMessage propiedad en el MessageThread clase es uno de esos casos. Cuando buscamos un hilo, mira métodos específicos en nuestra clase para determinar cómo debe manejar las referencias a otros objetos de colección. En nuestro caso, los siguientes métodos permiten tratar esta referencia como un Message ejemplo:

// Extracted from MessageThread.swift (http://tuck.cc/1w7jdOd)

// This method tells Kinvey to save the message in the lastMessage property
// when the thread is saved. If this method were not included, the message
// itself would not be saved when the thread is saved.
override func referenceKinveyPropertiesOfObjectsToSave() -> [AnyObject]! {
 return [
 "lastMessage"
 ]
}

// This maps the properties in the class to specific values in the Kinvey
// data store.
override func hostToKinveyPropertyMapping() -> [NSObject : AnyObject]! {
 return [
 "entityId" : KCSEntityKeyId,
 "lastMessage" : "lastMessage",
 "metadata" : KCSEntityKeyMetadata
 ]
}

// This method tells Kinvey that the lastMessage property is a member of
// the Messages collection. (You need to put the name of the Kinvey collection
// here and not the name of the class.)
override class func kinveyPropertyToCollectionMapping() -> [NSObject : AnyObject]! {
 return [
 "lastMessage" : "Messages"
 ]
}

// Here you tell Kinvey which class to map the lastMessage property to. This
// is how it knows how to build the object when it fetches it from the server.
override class func kinveyObjectBuilderOptions() -> [NSObject : AnyObject]! {
 let referenceMap:[NSObject : AnyObject] = [
 "lastMessage" : Message.self
 ]
 return [
 KCS_REFERENCE_MAP_KEY : referenceMap
 ]
}

Clases de modelos de datos en Swift

Para que las clases de modelos de datos funcionen correctamente en Swift, deben poder aprovechar el inicializador predeterminado. Esto significa que debe tener un valor predeterminado para cada propiedad dentro de la clase. Todavía puede aprovechar los inicializadores de conveniencia, como lo hemos hecho aquí con el Message clase:

// Extracted from Message.swift (http://tuck.cc/1w7kkgB)

// This initializer creates a Message instance based on the message text
// and the recipient ID. This is the initializer that is used when a
// user creates a new message in a conversation.
init(messageText:String, recipientId:String) {
 senderId = KCSUser.activeUser().userId
 self.messageText = messageText
 entityId = NSUUID().UUIDString
 metadata = KCSMetadata(userIds: [recipientId], includeActiveUser:true)
}

Nota: Para obtener más información sobre el almacén de datos y el modelado de datos en Kinvey, consulte la sección «Almacén de datos» guía.

Conclusión

A través de este proceso, hemos completado el núcleo de interacciones de Kinvey para la aplicación. Sin embargo, con todo esto en su lugar, aún no se han cumplido dos requisitos clave: permisos de datos y notificaciones push. En el próximo artículo, exploraremos el modelo de permisos en Kinvey, así como la funcionalidad de lógica empresarial proporcionada por la plataforma.

Deja un comentario