Cómo Crear Una Aplicación Simple para iPhone en iOS 5: Parte 1

Ray Wenderlich

Esta entrada está disponible también en: Chino simplificado, Inglés, Francés, Japonés, Coreano

La programación para iPhone es como una mariquita - ¡divertida y un poco intimidante!

La programación para iPhone es como una mariquita - ¡divertida y un poco intimidante!

Update 2/16/12: Completamente actualizado para iOS 5.

El iPhone es una plataforma de desarrollo increíble para los programadores independientes. Nunca ha sido tan fácil tener una idea, generar algo de código, y luego tenerlo a disposición de ¡millones de clientes potenciales!

Últimamente he estado recibiendo muchas consultas de personas que recién se encuentran con el mundo de desarrollo para iOS preguntándome como empezar. Es por esto que he pensado en la utilidad de escribir una serie de tutoriales diseñados a medida para principiantes.

En lugar de enfocarme exclusivamente en un tema, vamos a adentrarnos en la creación de una aplicación entera y completamente funcional desde el principio. Al finalizar, habrás probado un poco de distintas áreas relacionadas con el desarrollo para iPhone y te encontrarás listo para ir por más.

¿Entonces que aplicación vamos a desarrollar? Bueno, hay una historia detrás de esto..

La otra noche vi una foto de una Niña de la Tierra por primera vez y pensé que iba a enloquecer porque ¡era enorme y espantosa! A raíz de ello empezó mi obsesión por buscar todo tipo de bichos en internet. Entonces para compartir la diversión, vamos a hacer una aplicación precisamente para eso – ¡calificar bichos raros!

Mientras desarrollamos la aplicación, cubriremos algunos de los tópicos más utilizados en el desarrollo para iPhone:

  • Lo necesario para comenzar con el desarrollo en iPhone
  • Cómo almacenar los datos de tu aplicación en un Modelo
  • Cómo utilizar las vistas de tablas (Table Views) – incluyendo añadir y eliminar filas
  • Cómo crear una vista de detalles para una fila
  • Cómo dar soporte tanto a la orientación vertical (Portrait) como horizontal (Landscape)
  • Cómo utilizar controladores de navegación
  • Cómo utilizar un selector de imágenes
  • Cómo utilizar controles comunes de tipo campo de texto, botones y vista de imágenes
  • Cómo añadir iconos e imágenes por defecto
  • Bono: cómo gestionar operaciones de larga duración

Parece mucho pero no es necesario asustarse – ¡nosotros no le tememos miedo a los bichos!

En esta primera parte de una serie de tres, cubriremos como cargar el modelo con una lista de insectos y visualizarlos en una tabla. (Ir a Parte 2 o Parte 3)

Este tutorial es para desarrolladores novatos de iOS, sin embargo asume que tienes cierta familiaridad con el lenguaje Objective-C y la programación en general. Si eres completamente ajeno al Objective-C te recomiendo leer primero la guía Objective-C Programming Language Guide de Apple primero.

Lo que necesitas

Primero lo primero – para desarrollar en el iPhone necesitas una Mac. Casi cualquier Mac serviría siempre y cuando pueda ejecutar la última versión del sistema operativo Mac OS, Lion. Si estás buscando una salida económica puedes conseguir una Mac Mini por un muy buen precio y tendrás una máquina perfectamente capacitada para el desarrollo.

Luego, necesitas una copia de Xcode, el IDE de Apple para desarrollo en iOS. Si aún no lo has hecho, regístrate de forma gratuita en el iPhone Dev Center y descarga una copia de Xcode desde la Mac App Store.

Si así lo prefieres puede registrarte en el programa de desarrolladores, que por un pago anual, te permite distribuir tus aplicaciones en la App Store. Por otro lado si de momento lo que te interesa es probar el desarrollo en iOS la cuenta gratuita funcionará perfectamente.

Si todo empieza a tornarse más serio, es probable que te interese disponer de algún dispositivo físico (iPhone/iPhone 4/iPod Touch/iPad) también. Es cierto que puedes realizar muchas de las pruebas con el simulador pero algunas APIs no funcionan en él, y para realizar pruebas de rendimiento, un dispositivo real es necesario.

Eso es todo – si aún no lo has hecho, descarga una copia de Xcode, ejecútalo y ¡continuemos!

¡Hola, vista de tabla (Table View)!

Vamos a comenzar utilizando uno de los controles mas comunes en el iPhone – la vista de tablas. Probablemente has encontrado la vista de tablas en un gran número de aplicaciones, a continuación algunos ejemplos:

UITableView Examples

En fin, nuestra primera pantalla contará con una de estas vistas para desplegar esos ¡bichos intimidantes!

Comencemos dirigiéndonos a FileNew Project in XCode, select the iOSApplicationMaster-Detail Application, y haciendo click en Next.

Creating an app with the master detail application template

En la siguiente página, escribe ScaryBugs como nombre de producto, crea una cadena de texto única como identificador de la compañía (com.yourcompanyname o mejor aún com.yourname), selecciona el iPhone para la familia de dispositivos y asegúrate de activar las casillas para utilizar el Storyboard y la Cuenta Automática de Referencias (ARC). Luego haz click en Next.

Project Settings for scary bugs app

Selecciona la mejor ubicación para guardar tu proyecto y haz click en Create. Antes de hacer nada mas, vamos a verificar lo que tenemos hasta ahora. En la barra de herramientas de la parte superior selecciona iPhone Simulator de la lista, luego haz click en el botón Run. Si todo va bien, deberías ver lo siguiente a continuación en tu simulador:

The main screen created by the master detail template

Puedes accionar el botón “+” para crear una nueva entrada y luego seleccionar la nueva fila para ver el detalle:

Detail view created by master detail application template

Como puedes ver, contamos con un proyecto real y funcional. Es una ventaja de haber empleado la plantilla Master-Detail Application.

No vamos a entrar en los detalles de la plantilla ya que eso escapa del alcance de nuestro tutorial, sin embargo es importante destacar que contamos con una vista de tabla vacía y la vista de detalles lista para su uso – ¡sólo tenemos que introducir los datos!

Para hacerlo, vamos a crear una clase que nos permita hacer el seguimiento de los insectos.

Un modelo de bichos: Organización

Fíjate en la jerarquía de directorios en la sección del Project Navigator de Xcode:

The project navigator in Xcode

La plantilla viene configurada con un grupo raíz y un grupo de archivos adicionales (Supporting Files). Estos grupos están presentes sólo como referencia organizacional, por lo que puedes sentirte libre de modificar o cambiar lo que creas necesario. En nuestro caso, ya que vamos a tener una cantidad importante de archivos en el proyecto, procederemos a organizar las cosas un poco.

Primero, crearemos un grupo para almacenar los archivos de la interfaz de usuario. Para realizar este cambio, haz control-click en el grupo Scary Bugs y selecciona la opción New Group. Luego control-click en el nuevo grupo, seleccionar Rename y renombrar el grupo a “GUI”. Arrastra los archivos existentes desde la raíz al grupo GUI (sin incluir Supporting Files). Debe verse como se muestra a continuación:

Organizing Project Navigator tree, part 1

Ahora vamos a crear un segundo grupo y nombrarlo “Model” ya que vamos a agregar un par de clases para nuestro modelo de datos en él. El árbol debe lucir ahora como sigue:

Creating a group for the model

Antes de continuar, hablemos un poco de como vamos a organizar las cosas:

  1. ScaryBugData: Contiene el nombre y la calificación del insecto.
  2. ScaryBugDoc: Contiene una imagen en tamaño real, otra imagen de tipo thumbnail y el ScaryBugData.

La razón por la que configuramos todo de esta forma reside en la forma que utilizaremos para almacenar los datos en disco en los siguientes tutoriales, implementando ficheros compartidos, etc.

Un modelo de bichos: Implementación

Ok vamos a ello. Haz control-click en el grupo Model y haz click “New File…”. Selecciona la plantilla de clase iOSCocoa TouchObjective-C, y luego haz click en Next.

Creating a file with the Objective-C class template

Asigna a la clase el nombre ScaryBugData, coloca NSObject como subclase y haz click en Next.

Creating a class that derives from NSObject in Xcode

En la última ventana haz click en Create de nuevo. Si todo va bien, la sección del Project Navigaror debe lucir como vemos a continuación:

Project organization, part 3

Muy bien, es hora de crear nuestra clase ScaryBugData. Reemplaza el contenido de ScaryBugData.h con lo siguiente:

#import <Foundation/Foundation.h>
 
@interface ScaryBugData : NSObject
 
@property (strong) NSString *title;
@property (assign) float rating;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating;
 
@end

Esto es bastante sencillo – simplemente estamos declarando un objeto con dos propiedades – una cadena para el nombre del insecto, y un float para la calificación que le asignemos. Utilizamos dos propiedades para esto:

  • strong: indica que durante el tiempo de ejecución es necesario mantener una referencia fuerte de forma automática con el objeto. Es una forma elegante de decir que el contador ARC debe mantener al objeto en memoria tanto tiempo como exista una referencia a él, y luego liberarlo sólo cuando todas las referencias hayan desaparecido. Para mayor información consulta nuestro tutorial Beginning ARC in iOS 5.
  • assign: esto significa que la propiedad se configura automáticamente, sin ningún tipo de gestión de memoria. Es lo que usualmente se utiliza para crear tipos de dato primitivos (no objetos) como puede ser el punto flotante (float).

También definimos un inicializador para la clase de modo que sea posible asignar el título y la calificación cuando creamos un insecto nuevo.

Cambiamos ahora a ScaryBugData.m y reemplazamos el contenido con lo siguiente:

#import "ScaryBugData.h"
 
@implementation ScaryBugData
 
@synthesize title = _title;
@synthesize rating = _rating;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating {
    if ((self = [super init])) {
        self.title = title;
        self.rating = rating;
    }
    return self;
}
 
@end

De nuevo, realmente simple. Sintetizamos nuestras propiedades y luego creamos el inicializador para asignar valores a nuestras variables de instancia con los valores recibidos por parámetros. Fíjate que no es necesario liberar memoria (dealloc) ya que estamos utilizando ARC.

Eso es todo con respecto a ScaryBugData. Ahora sigamos los mismos pasos de arriba para crear una nueva subclase del tipo NSObject. Esta vez la llamaremos ScaryBugDoc.

Reemplaza el contenido de ScaryBugDoc.h con lo siguiente:

#import <Foundation/Foundation.h>
 
@class ScaryBugData;
 
@interface ScaryBugDoc : NSObject
 
@property (strong) ScaryBugData *data;
@property (strong) UIImage *thumbImage;
@property (strong) UIImage *fullImage;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage;
 
@end

Nada particular que destacar aquí – sólo hemos creado algunas variables/propiedades de instancia y un inicializador.

Reemplaza el contenido de ScaryBugDoc.m con lo siguiente:

#import "ScaryBugDoc.h"
#import "ScaryBugData.h"
 
@implementation ScaryBugDoc
@synthesize data = _data;
@synthesize thumbImage = _thumbImage;
@synthesize fullImage = _fullImage;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage {   
    if ((self = [super init])) {
        self.data = [[ScaryBugData alloc] initWithTitle:title rating:rating];
        self.thumbImage = thumbImage;
        self.fullImage = fullImage;
    }
    return self;
}
 
@end

Y eso es todo – ¡nuestro modelo de datos esta completo! Es hora de crear alguna data de ejemplo y desplegarla en nuestra vista de tabla.

Un tipo diferente de lista de bichos

Primero, vamos a configurar nuestra vista de tabla de modo que pueda manejar el despliegue de una lista con el contenido de ScaryBugDocs. Lo primero que debemos hacer es modificar nuestra vista de tabla para que retorne un número dinámico de filas (en lugar de la fila única que nos provee la plantilla).

Para lograrlo, nos dirigimos a MainStoryboard.storyboard. Esta sección te permite visualizar las diferentes “pantallas” de tu aplicación. Como puedes ver, la aplicación de momento cuenta con un controlador de navegación (lo que facilita desplazarse de una pantalla a otra), con el controlador raíz como pantalla principal y un controlador secundario para el despliegue de la vista de detalle.

Main Storyboard layout

Selecciona el controlador principal (Master View Controller) y, en el área de selección del panel izquierdo, marca la vista de tabla. En el inspector al lado derecho asegúrate que el valor de Content sea Dynamic Prototypes.

Setting table view to use dynamic prototype cells

Es esto lo que te permite implementar una vista de tabla de una sola celda en el editor del Storyboard, para luego crear instancias de dicha celda vía código fuente. Nosotros queremos una celda simple por lo que utilizaremos el estilo Basic.

Selecciona la celda de la vista de tablas a la izquierda y en el inspector de atributos asegúrate de configurar en modo Basic la propiedad Style. También configura el identificador (Identifier) como MyBasicCell.

Setting cell style and reuse identifier

Para más información de como crear celdas personalizadas, consulta nuestro tutorial Beginning Storyboards in iOS 5.

Ok, ahora que tenemos nuestra vista de tabla configurada correctamente, sólo necesitamos actualizar el código para alimentar la tabla con la lista de los insectos.

Procederemos a almacenar nuestro ScaryBugDocs en un arreglo del tipo NSMutableArray, el tipo de estructura que nos permitirá luego realizar modificaciones que afecten su tamaño sin ningún problema.

Añade la siguiente línea a MasterViewController.h entre las líneas @interface y @end:

@property (strong) NSMutableArray *bugs;

Esta será la variable/propiedad de instancia que utilizaremos para hacer el seguimiento de nuestra lista de bichos.

Ahora vamos a MasterViewController.m y realizamos los siguientes cambios:

// Al inicio del archivo
#import "ScaryBugDoc.h"
#import "ScaryBugData.h"
 
// Luego de @implementation
@synthesize bugs = _bugs;
 
// Al final de viewDidLoad
self.title = @"Scary Bugs";
 
// Reemplaza la sentencia "return" en shouldAutorotateToInterfaceOrientation con:
return YES;
 
// Reemplaza la sentencia "return" en tableView:numberOfRowsInSection con:
return _bugs.count;
 
// Reemplaza tableView:cellForRowAtIndexPath con:
- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView
                             dequeueReusableCellWithIdentifier:@"MyBasicCell"];
    ScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
    cell.textLabel.text = bug.data.title;
    cell.imageView.image = bug.thumbImage;
    return cell;
}

¡Finalmente algo interesante que comentar!

Antes de continuar, fíjate que hemos asignado la cadena “Scary Bugs” como valor de la propiedad “title.” Esta es una propiedad especial asociada (built-in) a los view controllers. Cuando un controlador de navegación despliega un view controller, este muestra el contenido de la propiedad “title” en la barra de título. Al configurar este valor lo que logramos es que en la barra superior se lea el texto “Scary Bugs.”

Luego retornamos “YES” en shouldAutorotateToInterfaceOrientation, con lo cual indicamos al sistema que debemos tener la capacidad de soportar todas las orientaciones. Dado que esta clase es del tipo UITableViewController no debemos hacer nada más – ¡la vista rotará de forma automática!

Cuando construimos una vista de tablas con filas dinámicas debemos sobre escribir numberOfSectionsInTableView y numberOfRowsInSection para indicarle al sistema cuantas secciones/filas debe desplegar en la tabla. Sólo tenemos una sección, por lo tanto no es necesario hacer ningún procedimiento adicional. Para establecer el número de filas, debemos retornar la cantidad de objetos en nuestro arreglo de insectos.

Finalmente implementamos tableView:cellForRowAtIndexPath, probablemente el método más importante al momento de crear una vista de tablas. Es aquí donde se configura la celda que será desplegada para una fila en particular. El sistema debe realizar la llamada a este método una vez por cada fila.

Vamos a ver este método en detalle dada la importancia que tiene:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView
                             dequeueReusableCellWithIdentifier:@"MyBasicCell"];
    ScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
    cell.textLabel.text = bug.data.title;
    cell.imageView.image = bug.thumbImage;
    return cell;
}

La primera línea realiza la llamada a una función de ayuda conocida como “dequeueReusableCellWithIdentifier”, la cual intenta devolver una celda reutilizable. ¿Por qué es esto necesario?

Bien, en principio es un tema de optimización del desempeño. Ten en cuenta que las vistas de tabla pueden contener un gran número de filas pero sólo un cierto número de ellas se despliegan en pantalla al mismo tiempo. En lugar de crear una celda cada vez que una nueva fila entra en pantalla, el sistema puede mejorar el rendimiento haciendo uso de la celda creada anteriormente y que no se encuentra ya en pantalla.

Si no se dispone de una celda para ser reutilizada, simplemente creamos una nueva desde la celda básica configurada anteriormente en el Interface Builder (“MyBasicCell”).

Es posible crear tus propias celdas o utilizar una estándar. En nuestro caso, la vista de tablas por defecto funciona perfectamente por lo que confirmamos la selección de este método al configurar el estilo con UITableViewCellStyleDefault.

Si tienes curiosidad sobre los distintos tipos de vistas de tabla y celdas puedes consultar la sección “Standard Styles for Table-View Cells” en Table View Programming Guide.

Finalmente configuramos la celda con los valores de textLabel e imageView (los cuales se encuentran disponibles en el estilo Basic).

Lo creas o no ¡esto es todo lo que necesitamos hacer! Ahora tan solo necesitamos establecer data de muestra para desplegar en nuestra vista de tabla.

¡Fotos de bichos!

Por supuesto, vamos a necesitar fotos de algunos insectos para esto. Puedes obtener algunas de internet o descargar esta colección Scary Bug Pictures que he encontrado en stock.xchng.

Una vez descargados los archivos, es cosa de arrastrar y soltar en la raíz de tu árbol en el Project Navigator. Cuando la ventana de opciones aparezca, asegúrate de seleccionar la opción “Copy items into destination group’s folder (if needed)” y hacer click en Add.

Adding scary bugs files to project

Luego abre el archivo AppDelegate.m y realiza los siguientes cambios:

// Al principio del archivo
#import "MasterViewController.h"
#import "ScaryBugDoc.h"
 
// Al principio de application:didFinishLaunchingWithOptions
ScaryBugDoc *bug1 = [[ScaryBugDoc alloc] initWithTitle:@"Potato Bug" rating:4 thumbImage:[UIImage imageNamed:@"potatoBugThumb.jpg"] fullImage:[UIImage imageNamed:@"potatoBug.jpg"]];
ScaryBugDoc *bug2 = [[ScaryBugDoc alloc] initWithTitle:@"House Centipede" rating:3 thumbImage:[UIImage imageNamed:@"centipedeThumb.jpg"] fullImage:[UIImage imageNamed:@"centipede.jpg"]];
ScaryBugDoc *bug3 = [[ScaryBugDoc alloc] initWithTitle:@"Wolf Spider" rating:5 thumbImage:[UIImage imageNamed:@"wolfSpiderThumb.jpg"] fullImage:[UIImage imageNamed:@"wolfSpider.jpg"]];
ScaryBugDoc *bug4 = [[ScaryBugDoc alloc] initWithTitle:@"Lady Bug" rating:1 thumbImage:[UIImage imageNamed:@"ladybugThumb.jpg"] fullImage:[UIImage imageNamed:@"ladybug.jpg"]];
NSMutableArray *bugs = [NSMutableArray arrayWithObjects:bug1, bug2, bug3, bug4, nil];
 
UINavigationController * navController = (UINavigationController *) self.window.rootViewController;
MasterViewController * masterController = [navController.viewControllers objectAtIndex:0];
masterController.bugs = bugs;

Aquí simplemente hemos utilizado el inicializador de ScaryBugDoc para crear cuatro insectos de ejemplo, pasando como parámetros los valores de título, calificación e imagen para cada uno de ellos. Los añadimos todos a un arreglo NSMutableArray y luego configuramos en nuestra vista de tabla.

Y hablando de ella, podemos obtener un puntero al RootViewController ya que sabemos que es el primer view controller en la pila del controlador de navegación. Existen otras formas de obtener dicho puntero pero esta es una de las mejores por su simplicidad.

¡Eso es todo! Compila y ejecuta tu aplicación. Si todo va bien deberías poder ver una lista de los bichos más atemorizantes en tu vista de tabla.

Scary Bugs Table View

¿A donde vamos ahora?

En el siguiente enlace encontrarás un proyecto de ejemplo con todo el código fuente desarrollado hasta el momento en el tutorial.

Por favor déjame saber si algo de lo expuesto anteriormente resulta confuso o si te gustaría que entrase en detalles en algún punto particular.

En la siguiente entrega, cubriremos lo necesario para crear una vista de detalles para los insectos de modo que podamos editarlos y calificarlos.

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

Comentarios de los Usuarios

3 Comments

  • Tengo problemas con el codigo del archivo:

    MasterViewController.m

    me salen 6 errores... que puede estar sucediendo?
    Maktub
  • Hola!
    He desarrollado tablas comunes con celdas verticales, pero mi duda es: Si quiero hacer dos celdas por rengln, cmo sera esto? o qu elemento tendra que arregar o para desarrollar.. Gracias!!!
    Angelica
  • I can not use Xcode to develop an app without paying 99$ as you say. Please help me out
    Casasal

Other Items of Interest

Newsletter Mensual de Ray

Suscríbete para recibir un boletín mensual con mis enlaces favoritos sobre programación, ¡y recibe un tutorial de longitud épica gratis como bonus!

¡Anúnciate con nosotros!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in September: iOS 8 App Extensions!

Sign Up - September

RWDevCon Conference?

We are considering having an official raywenderlich.com conference called RWDevCon in DC in early 2015.

The conference would be focused on high quality Swift/iOS 8 technical content, and connecting as a community.

Would this be something you'd be interested in?

    Cargando ... Cargando ...

Nuestros libros

Nuestro Equipo

Equipo de totorales

... 50 en total!

Update Team

... 15 en total!

Equipo Editorial

  • Ryan Nystrom
  • Alexis Gallagher

... 23 en total!

Code Team

  • Orta Therox

... 3 en total!

Equipo de Traducción

  • Lin Ma
  • Sonic Zhao

... 33 en total!

Expertos en la Materia

... 4 en total!