martes, 9 de abril de 2013

iOS: Mi primera aplicación


Lo prometido es deuda: crearemos nuestra primera aplicación con iOS.

Como punto de partida para este post tendremos que tener presente las siguientes publicaciones anteriores:

El objetivo de esta práctica es simple: crear una aplicación de dos pantallas. En la primera pantalla mostraremos un texto que se cambiará al pulsar un botón y dispondrá de un segundo botón para acceder a la pantalla secundaria, que mostrará un texto que le hemos pasado desde la principal. Básicamente es lo mismo que hicimos en su momento en Android: Crear una aplicación básica.

Os anticipo que este post va a ser laaaaargo.

Creación del proyecto

Una vez abierto XCODE, crearemos un  nuevo proyecto basándonos en la plantilla Single Application View dentro de iOS.


El asistente nos pedirá los datos del producto, así como el dispositivo para el que queremos desarrollar (por ejemplo, iPhone). Rellenaremos los datos y seguiremos los pasos hasta finalizar.



Una vez finalizado podremos escoger la versión del sistema operativo (iOS) que usaremos. Dejaremos la que nos venga por defecto, ya que no usaremos un dispositivo real, sino un simulador que nos incluye XCODE que es MUY bueno.



Lo primero que tendremos que tener en cuenta es que deberemos ir guardando a cada paso que demos. No es que sea una regla estricta, pero al ir moviéndonos por tantos archivos según el modelo MVC, es bueno tener guardado para asegurarnos que las referencias están actualizadas.

Dibujando las pantallas

Todo lo relacionado con el diseño de las pantallas y sus relaciones lo realizaremos desde el storyboard (MainStoryboard.storyboard). Abriremos el archivo e insertaremos una vista nueva arrastrando desde el menú Objects.



Posteriormente insertaremos en la primera pantalla un Label y dos botones (Round Rect Button). En la nueva pantalla (la secundaria) insertaremos solo un label.





Al seleccionar cada elemento, en el menú lateral de la izquierda podremos ver sus propiedades. A cada botón le cambiaremos el texto, indicando en el primero “Cambiar Texto” y en el segundo “Ir a Pantalla Secundaria”.




El objetivo es que la pantalla principal luzca así:
  


Ahora relacionaremos la pantalla principal con la secundaria, y para ello crearemos un Segue. Es muy fácil de hacer: con la tecla Alt pulsada hacemos clic sobre el botón “Ir a Pantalla Secundaria” y arrastramos hasta la pantalla secundaria. Esto nos dibujará una línea y nos resaltará la pantalla destino.
  


Al soltar el ratón, nos abrirá un menú contextual donde escogeremos el modo, y seleccionaremos modal (sobreescribirá a la anterior por completo).




En nuestro storyboard podremos ver como se dibuja el segue relacionando ambas pantallas.
  

Al seleccionar sobre el icono, en las propiedades podremos cambiar su identificador a SegIrASec (Segue Ir A Secundaria).
  


Con esto ya tendremos montada la transición entre pantallas. De hecho, si probamos la aplicación, veremos que al hacer clic en el botón, navegaremos a la segunda pantalla sin necedidad de haber “picado” ni una sola línea de código.

Creación del controlador

Al crear una aplicación basada en la plantilla simple, por defecto nos crea la pantalla principal con su controlador al que se le ha llamado ViewController. Si en nuestro storyboard pulsamos sobre View Controller, en el menú de propiedades de la pantalla podremos ver cuál es el controlador de la pantalla (ViewController) y, en el árbol de archivos, tendremos la cabecera de la clase (ViewController.h) y su implementación (ViewController.m).
  


Aprovecharemos que tenemos las propiedades de la pantalla principal abierta para indicarle un id a la pantalla principal: firstView.
  


De igual forma que con nuestra firstView, tendremos que tener una clase controladora de la pantalla secundaria. No obstante, no se crea por defecto, por lo que tendremos que crear un nuevo archivo iOS y seleccionar Object-C class.



En el asistente que se nos abre, indicaremos su nombre (SecondViewController) y le diremos que exitienda de UIViewController (clase base de la que extienden por defecto los controladores de las pantallas). El check de XIB lo dejaremos marcados, ya que la interfaz de la pantalla (su “dibujo”) lo haremos directamente en el storyboard.
  

Al finalizar nos habrá creado las dos clases del controlador: SecondViewController.h y SecondViewController.m.
  


Tras esto, ya solo nos quedará relacionar la pantalla del storyboard con el controlador, y esto lo hacemos seleccionando View Controller en la pantalla, y la clase SecondViewController. Aprovecharemos también para darle el identificador a la pantalla secondView.
  


Creando los conectores

Hasta ahora, solo hemos creado una pantalla en el storyboard y su controlador. No obstante, en la pantalla tenemos elementos que no hemos definido en el controlador, como labels y botones. Existen dos formas de realizar esas conexiones: por código o usando el asistente que nos proporciona XCODE.

Cambiaremos la vista a automática, lo cual nos dividirá la pantalla en dos: en la parte superior el archivo seleccionado (storyboard) y en la inferior un archivo relacionado. Al seleccionar en el storyroard nuestra firstView, veremos cómo automáticamente se nos abre en la parte inferior el archivo ViewController.h. Lo mismo ocurriría si lo hacemos con la secondView, que abriría el SecondViewController.h.



De nuevo haremos uso de la combinación alt+clic para seleccionar un elemento de la pantalla y arrastrarlo al código.



Al soltarlo se nos abrirá el asistente para crear la relación, en el cual indicaremos Outlet (elemento de la pantalla) y su nombre: lblTexto.



Haremos lo mismo con el label de la pantalla secundaria y le indicaremos el nombre lblTextoSec.


Si hacemos lo mismo con el botón para cambiar el texto, podremos escoger que el lugar de ser un elemento de pantalla lo que queremos relacionar con el código, sea una acción (Action), con lo que el nombre que indiquemos será el nombre de la función (evento) que generaremos: cambiarTexto.
  


En este caso NO haremos lo mismo con el botón “Ir A…” ya que lo tenemos asociado con una transición Segue.

Podemos comprobar en las propiedades de la pantalla las relaciones, así como dificarlas e incluso borrarlas. Si generamos por código tanto las acciones como los elmentos, desde aquí podremos crear la relación con la pantalla. Cuestión de gustos ;-).




Cambiando el valor del label

Si abrimos nuestro archivo ViewController.h veremos que ha quedado así:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *lblTexto;
- (IBAction)cambiarTexto:(id)sender;

@end

Y nuestro SecondViewController.h tal que así:

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *lblTextoSec;

@end

Ahora, lo que queremos hacer es que nuestro botón “Cambiar Texto” modifique el contenido del label lblTexto. Para ello, abriremos el archivo ViewController.h, y justo debajo de la clausula implementation añadiremos @synthesize lblTexto; para indicar que queremos trabajar con esa propiedad definida en la cabecera. Tras esto, en la función cambiarTexto que se ha creado de forma automática añadiremos el código para cambiar el texto:

- (IBAction)cambiarTexto:(id)sender {
    lblTexto.text = @"has cambiado el texto";
}

Con esto, ya podemos probar a ver como se cambia el texto del label al pulsar el botón.

Transición entre pantallas

La transición entre la pantalla firstView y secondView quedó definida con segue. No obstante, nosotros queremos que en esa transición se envie información de una pantalla a otra. Para ello, definiremos una propiedad en SecondViewController.h de tipo String cuyo nombre será texto que usaremos para enviar el mensaje. Declararemos también una función loadData, que se ejecutará una vez cargada la pantalla al completo y que asignará el texto al label lblTextoSec.

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *lblTextoSec;
@property NSString *texto;
-(void)loadData;
@end

Una vez hecho esto, en SecondViewController.m haremos syntetize de lblTextoSec y texto para poder usarlos en la implementación de la función loadData.

#import "SecondViewController.h"

@interface SecondViewController ()
@end

@implementation SecondViewController
@synthesize lblTextoSec;
@synthesize texto;
(...)

Y en la función ViewDidLoad invocaremos a loadData.

- (void)viewDidLoad
{
    [super viewDidLoad];
     // Do any additional setup after loading the view.
    [self loadData];
}

La implementación de loadData será tan simple como asignar texto a lblTextoSec.

-(void)loadData
{
    lblTextoSec.text = texto;
}

Nos queda la parte más compleja: pasar el texto de firstView a secondView. Al estar usando segues, UIViewController implementa una función previa a la ejecución de segues: prepareForSegue, donde podremos ver que segue se va a ejecutar y a que pantalla se va a llamar. Haremos uso de esta función para pasarle a firstView.texto el mensaje que queramos enviar. En ViewController.h importaremos SecondViewController.h para poder usar su declaración.

#import "SecondViewController.h"

Y la función prepareForSegue la escribiremos en ViewController.m.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSString * idseg = segue.identifier;
   
    if ([segue.identifier isEqualToString:@"segIrASec"])
     {
        SecondViewController *sw = segue.destinationViewController;
        sw.texto = @"texto desde viewcontroller";
    }
}

Y con esto y un bizcocho, tenemos listo nuestro código.