El Blog de ThXou

iOS Práctico, programación y otras cosas

Literales en Objective-C

| Comments

Los literales son simplemente unos valores que los programadores podemos escribir “tal cual” en el código. En Objective-C (y por lo tanto en C) ya conocemos algunos ejemplos de esto con los valores primitivos:

1
2
float altura = 23.5;
int piezas = 20;

Estos son: un literal float y un literal int respectivamente. Estos literales son comunes en la mayoría de los lenguajes, no obstante Objective-C tiene sus propios literales a parte de los mencionados

NSNotificationCenter Y Las Notificaciones

| Comments

Vuelvo a la carga con los tutes sobre iOS después de un tiempo ausente por proyectos personales.

Esta vez os voy a hablar sobre otro tipo de notificaciones, diferentes a las notificaciones locales que vimos hace un tiempo. Estas nuevas notificaciones básicamente encapsulan información acerca de algún tipo de evento. Hay objetos que registran estas notificaciones en lo que podemos llamar una “tabla de notificaciones”, esta tabla está administrada por un centro de notificaciones, que es un objeto NSNotificationCenter. Luego tenemos objetos que se registran como “Observadores” de estas notificaciones

Trabajando Con El Social Framework De iOS 6: SLRequest, Publicar en Twitter Y Obtener El Timeline

| Comments

Siguiendo con los tutoriales sobre iOS 6, hoy nos toca Twittear (o como se escriba) y mostrar nuestro timeline de Twitter en una aplicación.

Antes cuando queríamos comunicarnos con Twitter y obtener datos y actualizarlos había que hacer una conexión a través de OAuth con unos tokens y secret-keys, esto normalmente se hacía más digerible usando algún framework o clase externa que servía de interfaz de conexión entre el cliente y el servicio. Desde la llegada del framework de Twitter y la integración con iOS 5

Trabajando Con El Social Framework De iOS 6: Publicar en Twitter Y Facebook

| Comments

Aquí les traigo un tutorial bastante fresco sobre el recién nacido iOS 6. Como sabéis cada nuevo iOS trae consigo muchas novedades y este no va a ser la excepción, tenemos cientos de nuevas APIs y cambios con respecto a iOS 5, y por si fuera poco también tenemos 3 nuevos frameworks para estudiar e implementar en nuestras apps. Queda aún trabajo por hacer.

Hoy voy a comenzar con el primero de una serie de tutoriales para ir introduciéndonos en el mundillo de iOS 6 poco a poco. Empezaré con uno de los 3 nuevos frameworks que incluye este nuevo iOS: el Social Framework.

Este framework reemplaza al de Twitter y se hace más generico para ser compatible

iOS 6 Golden Master Ya Disponible Para Los Desarrolladores

| Comments

Tal y como se esperaba, hoy ha habido keynote y con muchas novedades interesantes: iPhone 5, nuevo iPod Nano, iOS 6, etc. Para todos los desarrolladores también ha salido la versión Golden Master del iOS 6 y la pueden descargar desde ya.

Para los que no lo saben, una versión Golden Master es una versión “casi” final, osea que es muy probable que la versión final sea similar o igual a esta.

Según Apple, la versión final de iOS 6 estará viendo la luz el 19 de setiembre y estará disponible únicamente para el iPhone 3GS, iPhone 4, iPhone 4S, iPod Touch 4G, iPad 2 y el nuevo iPad.

Aquí en el blog presentaremos tutoriales sobre iOS 6 el mismo día de la salida de la versión final, por lo tanto si eres desarrollador y quieres ir estando al tanto de lo nuevo de este OS, no olvides volver periódicamente.

Parsear Y Crear Ficheros en Formato JSON en iOS

| Comments

Desde la salida de iOS 5 Apple incluyó en su API la clase NSJSONSerialization, la cual nos permite convertir objetos JSON en objetos de Objective-C (que ya tocaba también) y viceversa de manera sencilla.

Para los que no saben que es JSON (JavaScript Object Notation), es un tipo de sintaxis que nos permite representar porciones grandes o pequeñas de datos para poder almacenarlos y/o intercambiarlos con otros entornos. Mucho más sencillo y pequeño que XML y además más rápido de parsear. Usa exactamente la misma sintaxis que usa JavaScript para crear objetos pero es totalmente

Keynote Para El 12 De Setiembre

| Comments

Parece que ya está confirmada a los medios una Keynote para el día 12 de setiembre, fecha tan esperada por algunos por la posible salida del iPhone 5 e iOS 6. Lo del iPhone 5 no está confirmado pero la sombra de la imagen de arriba sugiere mucho no?, esperemos que así sea y no nos llevemos una decepción como con la salida del iPhone 4S. El evento se va a realizar en el Yerba Buena Center en San Francisco según los medios a las 10 de la mañana de allí, 19:00 hora española.

Se espera el iOS 6 ya que 12 de setiembre es la fecha de caducidad de la beta 4 del SO, aquí en el blog tendremos preparados unos cuantos tutoriales para que vayáis aprendiendo sobre los nuevos frameworks de iOS 6 el día mismo de la salida.

Se estima que el dispositivo esté listo para la venta en Estados Unidos como en las otras ocasiones para el día 21 de setiembre, y si los cálculos son buenos, lo tendremos por España más o menos por el 5 de Octubre.

A ver si los que tenemos dispositivos antiguos, el iPhone 3GS en mi caso, ya podemos jubilarlos por uno como este.

Fuente | ActualidadIphone

Aprender a Usar URL Schemes en iOS - URL Personalizada

| Comments

Las URL Schemes permiten a las aplicaciones comunicarse, enviar y recibir mensajes y ejecutar acciones entre si a través de una URL personalizada. Pongamos un ejemplo, tenemos una aplicación que permite mostrar direcciones en el mapa, pues podríamos usar URL Schemes para que cualquier aplicación pudiera abrir direcciones en el mapa de nuestra aplicación.

Apple también tiene sus propias URL Schemes y seguramente las habrás visto en acción en páginas web que contienen números de teléfono y estos aparecen como enlaces, y cuando presionas en ellos se lanza la aplicación teléfono que hace una llamada a ese número, pues bien, aquí se utiliza la URL tel:. También están mailto: (para el correo), sms: y peticiones con http para los mapas y la aplicación de YouTube.

Registrando nuestra URL Scheme

Nosotros vamos a definir nuestra propia URL y para hacer esto hay 2 formas. La primera es a través del fichero info.plist. Como ya sabéis, este fichero esta compuesto por pares key-valor, así que añadimos una nueva key llamada CFBundleURLTypes (Al presionar enter aparecerá ”URL types”). Veremos que es un array de diccionarios y solo contiene uno y dentro una key llamada ”URL Identifier” (Su nombre original es CFBundleURLName), cuyo valor puede ser cualquiera, Apple recomienda que para que sea completamente único podríamos usar el de nuestro Bundle Identifier, en el caso de la app de ejemplo de este tutorial es: com.thxou.scheme.

Ahora agregamos a este diccionario una nueva key llamada CFBundleURLSchemes para definir el nombre de nuestra URL, al presionar enter su nombre cambiará a ”URL Schemes”. En este array de strings vamos a definir nuestras URL (Porque puede haber más de una) poniendo el nombre con el que queremos que se abra nuestra app. Al poner el nombre hay que tener en cuenta 2 cosas:

  1. Cuidar que el nombre no sea uno de los ya definidos por Apple, ya que ellos dan prioridad a las aplicaciones nativas antes que a la tuya.
  2. Cuidar que el nombre no sea el de cualquier otra aplicación, el SO actualmente no sabe como reconocer cual es la aplicación a la que pertenece el URL Scheme, por lo tanto puede que ninguna App se abra.

El esquema final debe lucir más o menos así:

Si ahora mismo escribes scheme:// en Safari, se abrirá inmediatamente la aplicación.

La segunda forma es más fácil. Ir a la raíz del proyecto, seleccionar el target de nuestra aplicación, luego la pestaña Info y al final de todo veremos el apartado URL Types, desde aquí también podemos añadir nuevas URL Schemes presionando el botón de abajo llamado Add y seleccionando Add URL Type.

Recibiendo la URL

Como en principio se abrirá la aplicación y no hará nada, vamos a pasarle información en esa URL y a mostrarla en la vista principal. El encargado de manipular la URL que viene desde afuera es el delegado de la aplicación (el AppDelegate de toda la vida) y para hacer esto necesita implementar el método application:openURL:sourceApplication:annotation. La secuencia que sigue la aplicación cuando se le pide que abra una URL es la siguiente:

Este es el proceso cuando la aplicación no está abierta. Si está abierta la única posibilidad es que esté en background, así que en vez de la parte de inicialización, se ejecuta el método applicationWillEnterForegound:, esto se debe a que se necesita que la aplicación esté ejecutándose en primer plano, entonces la aplicación es pasada a este estado y luego es ejecutado el método application:openURL:sourceApplication:annotation.

Para no hacer las cosas más complicadas vamos a pasar simples textos a través de la URL, es solo para mostrar el funcionamiento de este sistema. La URL que vamos a ejecutar desde Safari va a ser: scheme://cualquiercosa/parametro1/parametro2. Ahora nos toca implementar el método correspondiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    // comprobamos que se ha recibido una url
    if ([[url scheme] isEqualToString:@"scheme"])
    {
        // obtenemos el host de la url. En este caso será "cualquiercosa"
        NSString *urlHost = [url host];
        // obtenemos el path de la url por partes. No se cuenta el host
        NSArray *urlComponents = [url pathComponents];
        // componemos el string a mostrar
        NSString *texto = [NSString stringWithFormat:@"Contenido de la URL:\n\nHost: %@\nParámetros:\n1. %@\n2. %@", urlHost, [urlComponents objectAtIndex:1], [urlComponents objectAtIndex:2]];

        // lanzamos un alertView que nos muestre el string
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"URL Scheme"
                                                        message:texto
                                                       delegate:self
                                              cancelButtonTitle:@"Ok"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    else {
        // si no hay URL retornamos NO
        return NO;
    }
    return YES;
}

Después de esto, desde cualquier aplicación pueden enviar información a tu aplicación que tu puedas manipular con solo ejecutar este código desde un botón:

1
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"scheme://cualquiercosa/parametro1/parametro2"]];

No solo he querido explicar como trabajar con esto, sino también un poco de lo que ocurre detrás, últimamente me estoy aficionando a eso e igual me alargo un poco en los artículos, pero es necesario saber de que va la cosa para aprender bien. A por el próximo : ).

iOS: Enviar Correo Electrónico Desde La Aplicación

| Comments


Mientras trabajaba en mi aplicación Listed quise que los usuarios pudieran enviar sus listas por correo, y la verdad pensé que iba a ser difícil de hacer pero no fue así.

Apple provee una clase llamada MFMailComposeViewController dentro del framework MessageUI que hace muy sencillo el hecho de enviar correos sin tener que salir de la aplicación siquiera, esto, a través de la misma interfaz que usas en la aplicación Mail. Además te permite definir el contenido inicial de los campos del correo y también enviar uno o varios archivos adjuntos, como también provee de funcionalidad para responder a los eventos del usuario como enviar, cancelar o guardar un mensaje de correo.

La aplicación que toca esta vez va a permitir a los usuarios enviar un correo electrónico desde la aplicación. Usando el único método del delegado MFMailComposeViewControllerDelegate, vamos a mostrar al usuario mensajes dependiendo de si el correo se ha enviado, cancelado, guardado en borradores o ha fallado en el envío.

Nota:Es importante resaltar que cuando hablo de envío, me refiero a que el correo ha sido puesto en la cola de envío (carpeta de Salida en Mail), no que ya se ha enviado. Lo mismo para cuando cancelamos el envío, en realidad quiere decir que el correo no se ha puesto en la cola de envío.

Preparando el terreno

Para este proyecto he creado uno de tipo Single View Application y le he puesto de nombre ”emailMe”.

Lo primero que haremos será añadir el framework MessageUI a nuestra aplicación, luego vamos a definir un Outlet UILabel y una acción, así como también hacemos a ViewController conforme al protocolo MFMailComposeViewControllerDelegate. Para esto vamos al fichero ViewController.h y ponemos el siguiente código:

1
2
3
4
5
6
7
8
9
10
11
12
13
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>

@interface ViewController : UIViewControler <MFMailComposeViewControllerDelegate>
{
    UILabel  *estado;
}

@property (nonatomic, retain) IBOutlet UILabel *estado;

- (IBAction)enviarCorreo:(id)sender;

@end

Acto seguido pasamos a la interfaz de usuario, así que abrimos el fichero ViewController.xib y añadimos simplemente 2 objetos, uno de tipo UIButton y otro UILabel. El botón es para abrir la ventana modal desde donde escribiremos el correo y el label es para mostrar el estado del envío. Una vez añadidos, conectamos el UILabel con el código. Hacemos esto presionando la tecla Ctrl y arrastrando el cursor desde el File’s Owner hasta el objeto UILabel en el Interface Builder y luego seleccionando el correspondiente de la lista que aparece.

Implementación de la funcionalidad

Hay un método al que siempre tenemos que llamar antes de mostrar la interfaz de envío de correo, y es: canSendMail, este nos va a servir para verificar si el dispositivo del usuario está habilitado para usar esta característica. En caso contrario, yo he decidido mostrar una alerta diciendo que el dispositivo no soporta el envío de correo.

Abrimos el ViewController.m para implementar nuestro método creado anteriormente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@synthetize estado;

- (IBAction)enviarCorreo:(id)sender
{
    // verificamos si es posible enviar correo desde este dispositivo
    if ([MFMailComposeViewController canSendMail])
    {
        MFMailComposeViewController *email = [[[MFMailComposeViewController alloc] init] autorelease];

        email.mailComposeDelegate = self;

        // definimos el asunto del correo
        [email setSubject:@"Te envío una Web que mola"];

        // definimos el contenido inicial del correo
        NSMutableString *cuerpo = [[NSMutableString alloc] init];
        [cuerpo appendString:@"Hey!, he encontrado esta web y me ha gustado : )<br /><br /><a href='http://www.thxou.com'>http://www.thxou.com</a>"];

        // asignamos el cuerpo del mensaje y le decimos que lo interprete como HTML
        [email setMessageBody:cuerpo isHTML:YES];
        [cuerpo release];

        // adjuntamos una imagen desde nuestro bundle
        UIImage *imagen = [UIImage imageNamed:@"logo-thxou.png"];
        NSData *imagenData = UIImagePNGRepresentation(imagen);
        [email addAttachmentData:imagenData mimeType:@"image/png" fileName:@"thxoulogo"];

        // mostramos la ventana modal con la interfaz de envío de correo
        [self presentViewController:email animated:YES completion:nil];
    }
    else {
        // mostramos una alerta si el dispositivo no puede enviar correo
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                        message:NSLocalizedString(@"Tu dispositivo no soporta esta característica", nil)
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}

Como veis es muy sencillo implementar esta funcionalidad en una aplicación, con lo poco que hemos escrito ya es posible enviar un correo, no obstante aún nos falta la parte de manipular los eventos que dije al principio.

El método setMessageBody:isHTML: como puedes observar te permite asignar un contenido inicial para el correo. Si deseas que este contenido sea interpretado como código HTML, lo haces a través etiqueta isHTML:, la cual te permite especificarlo.

Luego tenemos el método addAttachmentData:mimeType:fileName: que nos va a permitir enviar datos adjuntos al correo. El primer argumento requiere un objeto de tipo NSData, así que lo que sea que queramos enviar tiene que estar primero convertido a este tipo de datos, en mi caso el logo de la web en formato .png.

El segundo argumento (mimeType:) es el tipo MIME del archivo que vamos a enviar, esto no te lo tienes que inventar ya que es un stardard predefinido y puedes ver el tipo MIME correspondiente a tu archivo en http://www.iana.org/assignments/media-types/. El tercer argumento es simplemente el nombre que deseas que tenga el archivo cuando sea transferido a su destino. Puedes repetir este método para cada uno de los archivos que desees adjuntar.

Hay otros métodos como setToRecipients:, setCcRecipients: y setBccRecipients: que cumplen exactamente la misma función que en un correo ordinario.

Manipulando el resultado del envío

Como se puede ver en la línea 8 del código de arriba, asignamos como delegado a la clase ViewController, por lo tanto esta va a ser la encargada de cerrar la ventana desde donde enviamos el correo y manipular los resultados del envío, por lo tanto se espera que también implemente el método delegado mailComposeController:didFinishWithResult:error: de la clase MFMailComposeViewControllerDelegate. Nosotros si lo haremos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            self.estado.text = @"La operación ha sido cancelada";
            break;
        case MFMailComposeResultSaved:
            self.estado.text = @"El correo ha sido guardado en la carpeta borradores";
            break;
        case MFMailComposeResultSent:
            self.estado.text = @"Correo puesto en la cola de envío satisfactoriamente";
            break;
        case MFMailComposeResultFailed:
            self.estado.text = @"No se ha podido enviar o guardar el correo debido a un error";
            break;
        default:
            break;
    }

    // cerramos la ventana modal de envío de correo
    [controller dismissViewControllerAnimated:YES completion:nil];
}

Dependiendo de cual sea el evento, se devuelve un código de resultado diferente, esto nos permite personalizar la respuesta en cada caso.

Conclusión

Hoy hemos aprendido a enviar un mensaje de correo electrónico desde la misma aplicación. También hemos aprendido a mostrar la interfaz de envío con unos valores iniciales por defecto, así como a interceptar los mensajes de estado del envío del correo. Con respecto a esta clase, no hay mucho más que aprender, tan solo queda un par de cosas relacionadas con los mensajes de error en el método delegado, pero por lo demás, si haz comprendido bien este tutorial, ya puedes decir que dominas la clase MFMailComposeViewController :). No obstante para más detalle acerca de esta clase puedes pasarte por la documentación un momento, que siempre viene bien.

Espero que les haya gustado y servido. Cualquier duda, objeción o sugerencia la espero en los comentarios.

iOS: Textos Con Fuente Personalizada Usando UIFont

| Comments

Es muy probable que ya te hayas encontrado con algunas aplicaciones que no utilizan el tipo de fuente por defecto del sistema, y que esto, junto con una buena interfaz gráfica, lucen mucho mejor. No tengo ni idea como estos desarrolladores lo han hecho, pero aquí te muestro una forma sencilla de hacerlo usando un método llamado fontWithName:size: de la clase UIFont. Este método de clase nos devuelve un objeto de fuente para un nombre y tamaño personalizado y lo aplicamos a la propiedad font de algunos objetos como: UILabel, UITextField, UITextView, UIButton, etc. Las fuentes personalizadas están disponibles desde iOS 3.2 en adelante, incluido iOS 5, así que asumo que cumples los requisitos para seguir el tutorial sin problemas.

Vamos a crear un proyecto desde cero para mostrar paso a paso el sencillo procedimiento que hay que seguir para configurar las fuentes y luego utilizarlas. Lo primero es crear un nuevo proyecto, yo he usado un Single View Application y le he puesto de nombre ChangeFont.

Paso 1. Añadiendo las fuentes

Una vez tengamos nuestro proyecto ya creado, vamos a buscar las fuentes que queremos utilizar dentro de nuestra aplicación. Para esto pueden ir a páginas web como fontreactor, que es el lugar de donde yo saqué las mías para hacer este tutorial. Las fuentes deben tener extensión .ttf u .otf.

Una vez ya las tengamos descargadas, arrastramos los archivos con extensión .ttf u .otf al árbol de directorios de nuestra aplicación en XCode (El Bundle). Nos saldrá una ventana como esta:

Si no está seleccionado desde antes, pues selecciona la opción: ”Copy items into destination group’s folder (id needed)”, esto hará que las fuentes (en general cualquier fichero) se copien también en el Bundle de la aplicación y no solo se guarde una referencia a la ubicación original. Aquí también hay algo que notar, y es que en el apartado ”add to targets”, los targets aparecen sin seleccionar. No seleccionar uno causará que no se muestren las fuentes cambiadas y esto es un problema que más tarde puede ser difícil de descubrir, por lo tanto nosotros lo seleccionaremos y luego daremos click en ”Finish”.

En caso de que se te pasara por alto marcar el target en alguna otra aplicación, la solución es seleccionar en la lista de directorios de la izquierda, la raíz del proyecto. Luego seleccionar el target (ChangeFont en nuestro caso) y después ir al apartado ”Build Phases” (Fases de construcción). Aquí encontraremos la fase ”Copy Bundle Resourses”. Cuando la aplicación es compilada para mostrarse en el simulador (o el dispositivo), esta fase se encarga de copiar todo lo que tenemos en la lista al Bundle del ejecutable de la aplicación. Así, al no seleccionar el target anteriormente, no añadimos las fuentes a esta lista y por lo tanto le dijimos a XCode que no incluya las fuentes cuando se compile el proyecto.

Así que si no lo hicimos ya, hacemos clic en el botón ”+” y añadimos las fuentes al Copy Bundle Resourses.

Paso 2. Configurar el archivo info.plist

Lo siguiente será añadir una nueva key al archivo info.plist de la aplicación. Lo abrimos y añadimos una nueva entrada llamada UIAppFonts (Al presionar enter, cambiará automáticamente de nombre a ”Fonts provided by application”). Esta key es en realidad un array, y en cada campo de este array escribiremos el nombre exacto de cada una de las fuentes que hayamos añadido a nuestro Bundle, con la extensión del fichero incluida como se puede ser en la siguiente imagen.


Esto sería todo lo que a configurar las fuentes se refiere. Ahora pasemos a tocar un poco de código.

Paso 3. Coding!

Para mostrar los resultados de esto, he creado 5 Outlets UILabel y los he conectado con sus respectivos UILabel en el Interface Builder, así que lo único que nos queda es asignar a la propiedad font de estos labels, la fuente que queremos utilizar, y como expliqué en el primer párrafo de este artículo, esto lo hacemos a través del método fontWithName:size: de la clase UIFont:

1
2
3
4
5
6
// asignando las fuentes
[self.fuente1 setFont:[UIFont fontWithName:@"appleberry" size:FONT_SIZE]];
[self.fuente2 setFont:[UIFont fontWithName:@"BilloDream" size:FONT_SIZE]];
[self.fuente3 setFont:[UIFont fontWithName:@"SweetHomeOklahoma" size:FONT_SIZE]];
[self.fuente4 setFont:[UIFont fontWithName:@"asongforjennifer" size:FONT_SIZE]];
[self.fuente5 setFont:[UIFont fontWithName:@"thebeautifulones" size:FONT_SIZE]];

Aquí viene lo interesante. Como podéis ver, en la etiqueta fontWithName: se muestra un nombre relacionado, pero no idéntico, al nombre de las fuentes que están en el Bundle. Bien, esto es porque el string con nombre de la fuente que se le tiene que pasar como argumento a este método no es el del nombre del fichero sino el ”PostScript name”. Para saber cual es el PostScript name de una fuente solo tenemos que abrir la aplicación ”Font Book” que viene con el sistema operativo (Usar spotlight para encontrarlo):

Al abrirla tenemos que seleccionar la fuente de la que queremos saber el PostScript name y listo, en la sección de más a la derecha veremos una descripción detallada de la fuente y en la primera línea el PostScript name. Si no vez el tipo de fuente que buscas es porque no la tienes instalada, así que haz doble click en el fichero de la fuente e instala, aparecerá inmediatamente.

Ahhh, me olvidaba, FONT_SIZE es una constante que he definido más arriba en el código para facilitarme las cosas por si posteriormente deseo cambiar ese valor, así me ahorro no tener que cambiarlos todos uno por uno. Pruébalo, te ahorrarás tiempo.

Esto es todo. Me iba a dormir pero al final he decidido terminar el tutorial :). La aplicación terminada luce así:


Espero que os haya servido. En el siguiente botón pueden descargar los archivos del tutorial. No olviden compartir estos tutoriales con la mayor cantidad de gente posible a través de las redes sociales.