Curso de iOS7: UITableView, Listados de información en Pantalla (I)

No hay aplicación que no tenga un listado en pantalla. Para esto existe el componente UITableView.

Al heredar de UIScrollView es una vista que es desplazable verticalmente. Lo cual nos viene muy bien ya que nos permite añadir mucha información aunque la pantalla no pueda llegar a presentarla toda de golpe. Según vayamos bajando podremos ver más información.

Podemos añadirlo a cualquier escena y arrastrando el TableView desde el Object Library:

Secciones y Filas

Al ser sólo un listado podemos pensar que es un componente simple, pero no es así. Para empezar puede manejar secciones (sections). Las secciones son como distintos apartados dentro del listado. Y dentro de cada sección puede manejar tantas filas (rows) como sea necesario. No es obligatorio que todas las secciones tengan el mismo número de filas. Por lo que podemos añadir tantas secciones como queramos y tantas filas en cada sección. 

Pies y Cabeceras

Todas las secciones disponen de un pie y una cabecera de sección.  Como cabría esperar la cabecera se coloca encima de la sección y el pie justo debajo.

Tipos de Contenido

El UITableView tiene dos tipos de contenido: Dinámico y Estático.

El modo dinámico nos obliga a tener que programar elementos en pantalla y en el modo estático podemos añadir elementos manualmente desde el propio Storyboard. 

Static Cells

Cuando estamos en el modo Estático podemos cambiar manualmente el número de secciones desde el inspector de atributos:

Aquí podemos ver que en el atributo Content está seleccionado Static Cells, es decir el modo estático. Si quisiéramos podríamos cambiarlo a Dynamic Cells.

También podemos cambiar el número de secciones con el atributo Sections. También podemos elegir el Estilo de las secciones así como el tipo de separador.

A la hora de seleccionar hay muchas maneras distintas de hacerlo. O pueden tener distintos tipos de usos. Para ello en el atributo Selection podemos elegir entre selección múltiple o simple.

La selección simple suele utilizarse cuando queremos que al pulsar una fila de una sección haga algo en concreto.

Si lo que quisiéramos hacer es que se pudieran seleccionar varios elementos del listado pondríamos Single Selection. Por temas de simplicidad en la explicación nos centraremos en la selección simple.

Para añadir una celda a una sección basta con arrastrar un UITableViewCell dentro de la sección que queremos ampliar.

Nota: Las Static Cells son muy cómodas cuando queremos hacer un formulario largo. Para la pequeña pantalla de un iPhone, es muy útil usarlos.

Obligatorio: Si queremos utilizar un TableView con celdas estáticas el controlador que asignemos a esa escena debería heredar de un UITableViewController. En este caso el TableView será el view del controlador.

Celda Dinámicas

Aunque las celdas estáticas pueden estar bien para poder utilizarlas desde diseño, para los programadores son mucho más interesantes las celdas dinámicas. Aunque nos obliga a realizar una implementación algo extensa, es mucho más flexible. La funcionalidad principal es la de presentar la información de uno o más Arrays de datos. 

UITableViewCell

Las filas son representaciones visuales del  objeto UITableViewCell. En el caso de las celdas estáticas podemos colocarle el estilo manualmente, en las celdas dinámicas lo tendremos que hacer desde programación. 

    Propiedades principales

    Las propiedades principales del objeto UITableViewCell son:
    • textLabel: etiqueta principal de texto
    • imageView: imagen opcional que podemos presentar en la celda, normalmente se coloca a la izquierda de la celda.
    • accesoryType: tipo de icono opcional que podemos presentar. Normalmente se coloca a la derecha de la celda.
    • detailTextLabel: etiqueta opcional, no disponible en el estilo Default.

    Estilos de Celda

    Existen 4 estilos predefinidos para las celdas, a mayores de los que podamos crear nosotros manualmente:
    • UITableViewCellStyleDefault: Este el único estilo que no tiene detailTextlabel. Es el más básico de todos
    • UITableViewCellStyleSubtitle: el textLabel está encima y el retail debajo.
    • UITableViewCellStyleValue1: el textLabel se pone a la izquierda en color negro y el detail la derecha en azul.
    • UITableViewCellStyleValue2: el textLabel está la izquierda en azul y el detail a la derecha en negro.

    Cómo relacionar el TableView con el ViewController

    Para relacionar el TableView deberemos dar una serie de pasos claros:
    • En la escena debería haber ya un TableView
    • Colocar un TableViewCell dentro del TableView en la escena
    • Colocar en el .h del View Controller de la escena donde hayamos colocado el UItableView la implementación de los protocolos UITableViewDelegate y UITableViewDatasource.
    • Relacionar el delegate y el datasource del TableView desde la escena con el ViewController:
      • Seleccionar el TableView
      • Pulsar el botón derecho
      • En el menú contextual arrastrar el círculo del delegate hasta el View Controller, de una manera muy parecida a como lo hicimos con los TextField.
      • Hacer lo mismo con el delegate
      • De esta manera ya estará relacionado la vista con el controlador

    TableViewController

    Los TableViewController son un tipo especial de escena que nos permite añadir una escena que ya tiene integrado un TableView y un TableViewCell:
    Cuando lo arrastramos al storyboard quedaría más o menos así:
    Lo bueno de utilizar este tipo de ViewController en el storyboard es que ya tiene todo lo necesario para poder funcionar con él. Sólo habría que asociarlo con una clase que herede de UITableViewController.

    Cómo implementar los métodos mínimos para que funcione un TableView en el controlador

    • Los pasos son los siguientes:
      • – (NSInteger) numberOfSectionsInTableView: esto nos devolverá el número de secciones, por defecto si no se implementa no pasa nada devolverá 1, pero lo dejamos para poder jugar con ello.
      • – (NSInteger) tableView:numberOfRowsInSection: este método es requerido, nos debería devolver el número de filas en cada sección que nos pasan como parámetro
      • – (UITableViewCell*)tableView:cellForRowAtIndexPath: esto debería devolver un objeto UItableView dependiendo del IndexPath, que es un objeto con dos propiedades: row y section, fácil no?
      • Los dos primeros métodos son fáciles, sólo deben devolver un número, pero el tercero tiene más chicha.

    Ejemplo de implementación de los métodos del Datasource

    -(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
        return 1;
    }
    – (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return 2;
    }
    – (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@”Cell”];
        
        // Configure the cell… setting the text of our cell’s label
        cell.textLabel.text = @”Título”;
        cell.detailTextLabel.text=@”texto detalle”;
        cell.imageView.image=[UIImage imageNamed:@”pilar-rubio.jpg”];
        cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
        return cell;
    }
    Como podemos ver estamos diciéndole al tableView que tiene 1 sección y dos filas en cada sección. Por lo que debería presentar dos filas en la pantalla.
    Respecto al método cellForRowAtIndexPath. La implementación tiene ter partes claramente diferenciadas. Primero realiza la inicialización de un objeto UITableViewCell indicando el estilo visual y un nombre reutilizable. En este caso se utiliza el estilo UITableViewCellStyleSubtitle, por lo que dispondremos del atributo detailTextLabel.
    Después realiza el rellenado de la celda, en concreto de las propiedades textLabel, detailTextlabel ImageView y del accesoryType. 
    Con esta implementación al ejecutarlo debería quedar más menos así:
    Licencia Creative Commons

    Curso de iOS7: Manejo de imágenes: UIImageView y UIImage, Images.xcassets

    UIIMageView

    No hay aplicación que no controle imágenes. Para ello deberemos conocer y saber manejar el UIImageView que es la vista principal para el manejo de imágenes.

    Este componente principal nos permite arrastrarlo a una escena como siempre. En principio será una View aun poco sosa:
    Lo importante son las propiedades que tenemos disponible para esta vista:
    En las imágenes disponemos de dos estados, normal y highlighted. Podemos elegir una imagen que asignar a cada uno de los estados. De normal, con asignar una al atributo image sería suficiente para presentarla en el ImageView.

    El atributo principal es image.

    También disponemos de las propiedades típicas de UIView:

    • hidden
    • Opaque
    • alpha
    • tag
    • etc…
    Crearemos un IBOutlet para el UIImageView de la manera habitual en el fichero de cabecera del ViewController.h:

    Inclusión de imágenes

    Como siempre será necesario incluir en el proyecto alguna imagen. Esto podemos hacerlo arrastrando cualquier imagen desde el finder hasta las carpetas de proyecto. Esto nos sacará un diálogo similar a este:

    Debemos recordar de dejar marcada la opción de copiar  los ítems al proyecto y que esté marcada la opción de Add to targets del proyecto de la aplicación que estamos realizando.
    Así nos aparecerán las imágenes en el proyecto:
    Y una vez añadidas nos permitirá colocarlas en los atributos del objeto:

    Carpeta ArtWork

    Esta es el típico grupo (como se llaman las carpetas dentro de Xcode) que se suele crear para guardar las imágenes que se vana distribuir con el proyecto. Para crearlo deberemos pulsar botón derecho sobre la carpeta del proyecto, la que contiene el código fuente del proyecto y pulsar en la opción New Group, o sobre la opción New Group with Selection teniendo seleccionadas las imágenes que queremos incluir en el nuevo grupo y nos saldrá una nueva carpeta en el proyecto donde podremos escribir el nombre:

    Una vez cambiado el nombre nos debería aparecer más o menos así:

    En este caso como ya habíamos seleccionado las imágenes al crear el grupo y hemos pulsado en New Group with Selection nos ha metido las imágenes directamente dentro del grupo.
    Si no hubiera sido así sólo sería necesario seleccionar las imágenes y hacer un Drag and Drop sobre la carpeta en el Navegador del proyecto.

    Métodos principales

    Veamos ahora los métodos principales con los que podemos trabajar con el UIImageView:

    • initWithImage: este método nos permite inicializar un objeto indicando cual es el UIImage que queremos cargar.
    • setImage: permite pasar como parámetro un UIImage que tenga ya la imagen cargada.
    • startAnimation: permite iniciar una animación 
    • stopAnimation: para la animación que estemos realizando

    UIImage: Una imagen en memoria

    Como podemos ver lo principal el el objeto UIImage, que es el que nos permite inicializar el Objeto de vista. Los formatos permitidos para el objeto de imagen son:
    • PNG
    • JPEG
    • GIF
    • TIFF
    • BMP
    • ICO
    • CUR
    • XBM

    Inicialización

    Ahora veamos cómo podemos llegar a inicializar una imagen con los ficheros de imagen que hemos incluido en el proyecto. Para ello será necesario hacer uso del método imageNamed del objeto UIImage:

    Una vez cargada la imagen sólo deberíamos pasarla a la vista:

    Carga de una Imagen desde Internet

    Para ello es necesario que dispongamos al menos de una una dirección URL que nos permita saber donde está la imagen que queremos cargar. Esta URL será un literal de una NSString.
    Una vez se sabe desde que URL tenemos que descargar la imagen, debemos rellenar un objeto NSURL que es el formato principal de acceso a URL’s de la biblioteca Fundation.
    Una vez inicializado el objeto NSURL cebemos crear un nuevo objeto NSData, que el que dispone del método dataWithContentsOfURL:objetoUrl que es el que permite realizar la petición web para descargar la imagen y dejarla en el objeto de datos.
    Una vez se ha descargado la imagen podemos inicializar el objeto UIImage con los datos descargados mediante el método initWithData:datos . 
    Lo cual ya nos permite disponer en memoria de un objeto con el contenido de la Imagen de internet. Por lo tanto ya podemos asignarlo al UIImageView mediante el método setImage:imagen2 .
    Este tipo de procesos que pueden llevar bastante tiempo, suele convenir llevarlos a hilos paralelos de ejecución, como explicaremos en posteriores temas.

    Carga de una imagen desde la Galería de fotos

    Para cargar una imagen desde la galería de fotos en iOS es necesario hacer uso de un tipo especial de UIPicker es el UIImagePickerController. Este picker nos permitirá escoger entre las fotos que tenemos en la galería y nos la devolverá a nuestro ViewController mediante un método definido en el delegado de dicho UIImagePickerController:

    – (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

    De esta manera podremos manejar la imagen que nos devuelvan y hacer lo que queramos con ella.

    Llamando al Picker de Imágenes

    Para ello hemos colocado un botón en la escena y hemos creado un IBAction que es llamado con el evento Touch Up Inside y hemos indicado en el fichero de cabecera del controlador que queremos implementar dos protocolos UIImagePickerControllerDelegate,UINavigationControllerDelegate . El primero de ellos es el que nos permite gestionar las funciones necesarias para que funcione el picker el segundo nos permite manejar las llamadas entre escenas, ya que vamos a llamar a un escena de sistema que es la que permite escoger la imagen de la galería. 
    Dentro del flujo de nuestra aplicación al hacer el salto a la escena del picker, perderemos el control momentáneamente cediéndolo al sistema. Y luego volveremos a ejecutar código de nuestro controlador cuando volvamos del picker.
    Veamos el código de llamada al picker de imágenes dentro del IBaction creado:
    Como vemos en la captura:
    • Inicializamos el picker de la manera habitual
    • Indicamos que el delegado del picker es la clase del controlador
    • Indicamos que queremos permitir la edición de la imagen
    • Indicamos la fuente, desde donde vamos a coger la imagen, en este caso es UIImagePickerControllerSourceTypeSavedPhotosAlbum es decir la galería.  
    • Lanzamiento del picker con el método resentViewController:picker animated:YES
    De esta manera nos saldrá una pantalla de selección de imagen de la galería.

    Manejando la Imagen seleccionada desde la galería

    El usuario ahora tiene dos opciones:
    • Elegir una foto
    • Cancelar la selección 
    En ambos casos volveremos a nuestro controlador cuando termine.
    En el caso de que el usuario haya elegido una foto se ejecutará uno de los métodos del protocolo UIImagePickerControllerDelegate:
    Como podemos ver el método didFinishPickingMediaWithInfo nos pasará toda la información del objeto seleccionado llamado info.
    Lo primero que hacemos es quitar el Picker de la vista y luego obtenemos desde el objeto info la imagen original guardada en la galería. Como es un diccionario lo hacemos a través del método objectForKey y le pasamos como parámetro su clave @”UIImagePickerControllerOriginalImage” . Esto nos devolverá la UIImage que luego pasamos a la vista.
    En el caso de que nos hayan cancelado la selección de la imagen deberíamos implementar un método que nos permite capturar esta acción:
    De esta manera podemos asociar cualquier acción por si el usuario cancela.

    Capturar una imagen desde la cámara

    Funciona de una manera bastante parecida a la selección de una foto de la galería, en este caso hemos asociado otro IBAction distinto para distinguir los códigos:
    como puede verse a través del picker intentamos averiguar si está la cámara disponible mediante el método isSourceTypeAvailable donde le pasamos como parámetro la fuente que selecciona la cámara UIImagePickerControllerSourceTypeCamera .
    Si no está disponible intentamos llamar al método que controla la llamada a la galería. Pero en el caso de que dispongamos de cámara hacemos los mismos pasos que hicimos anteriormente con la llamada a la galería:
    • Inicialización del picker
    • Selección del delegado en nuestro controlador, para que encuentre las funciones del protocolo UIImagePickerControllerDelegate
    • Selección de la cámara
    • Lanzamiento del picker
    NOTA: cabe destacar que en el simulador del iOS que viene con el Xcode no disponemos de cámara así que para poder probar esta funcionalidad será necesario disponer de un dispositivo físico, estar dado de alta en un Developer Program, tener asociado nuestro dispositivo a nuestra cuenta de developer y lanzar la ejecución de nuestro programa en ese dispositivo físico.

    Guardar una imagen en la galería

    Otra de la funciones típicas con imágenes es la necesidad de guardar imágenes dentro de la galería. Para ello deberemos utilizar el UIImageWriteToSavedPhotosAlbum que es una de las funciones definidas en el UIKit.h. 
    Veamos un ejemplo de funcionamiento:
     Los parámetros de llamada a la función son los siguientes:
    • El objeto UIImage que queremos guardar, en este caso le pasamos la imagen del UIImageView que tenemos puesta en ese momento.
    • La clase responsable de implementar los métodos que necesitamos para funcionar, en este caso el controlador
    • El método responsable de manejar por si hay algún error en el guardado: didFinishSavingWithError:contextInfo
    • La información del contexto, por si es necesaria, en este caso no lo es
    De esta manera si hay algún problema intentará ejecutar el método que le hemos indicado a atrvés del selector:
    Comprobamos si ha habido algún error con un if y actuamos en consecuencia.

    Images.xcassets

    Este fichero especial del proyecto permite manejar las imágenes de Iconos de lanzamiento y las Imágenes de Lanzamiento del proyecto:

    al pulsar sobre él nos da acceso a dos categorías principales:

    AppIcon nos permitirá seleccionar los iconos de lanzamiento de la aplicación. Los iconos que tendremos disponibles desde el Home de iOS:

    LaunchImage por su parte nos permitirá colocar las imágenes de lanzamiento de la aplicación:

    Como podemos ver en ambos casos disponemos de varios tamaños, las explicaciones necesarias para el diseño de los iconos las tenemos disponibles desde la propia ayuda de Apple.

    Dejo por aquí un tutorial en video que puede ser interesante para el manejo de assets con el Images.xcassets:

    Licencia Creative Commons

    Curso de iOS7: UITabBarController, combinado con la Navigation Controller

    Otro de los componentes principales de la navegación es el Tab Bar Controller. Este componente nos va a permitir manejar una serie de pestañas debajo de la escena que será relacionadas con otras escenas. Al pulsar cada una de las pestañas abrirán en la parte superior la escena que hayamos seleccionado. Para poder explicar cómo funciona crearemos un proyecto de Single View Application.

    Al entrar al storyboard deberíamos ver lo un View Controller. Borramos el View Controller, seleccionándolo y dandole a la tecla de borrar. Esto nos debería dejar un storyboard limpio.

    Incluyendo un Tab Bar Controller

    Para incluir el Tab bar controller lo buscamos en la Biblioteca de Objetos:
    Al arrastrarlo sobre el Storyboard deberíamos ver lo siguiente:
    Como podemos ver se nos ha colocado el Tab Bar Controller como escena principal, y se nos han agregado dos View Controller más. Cada uno de ellos nos aparece enlazado con el Tab Bar Controller mediante un segue de tipo Root View Controller. De una manera muy parecida a como vimos en el caso del Navigation Controller.
    Fijemonos en detalle como se ve el Tab Bar en el Storyboard:
    Como podemos ver tenemos dos nuevas pestañas en la barra. Cada una de ellas representa a otra escena. La Item 1 representa a la primera escena:
    Y el Item 2 representa a la segunda escena:

    Propiedades del Bar Item

    En ambos casos podemos modificar el Item de la pestaña seleccionándolo, desde su escena asignada, a través de sus propiedades:

    Como podemos ver tenemos lo siguiente:

    • Title: el texto que sale en la pestaña
    • Image: imagen asignada
    • Tag: identificativo del item
    • Enabled: posibilidad de habilitar o deshabilitar el elemento
    Vemos que al modificar el título en las pestañas de los elementos nos aparecen modificadas las pestañas en el tab bar controller:
    Si asignamos un color de fondo a cada Escena secundaria, veremos, cuando vayamos a ejecutarla, el funcionamiento de la barra de pestañas. Para ello seleccionamos el view Principal de la escena secundaria:
    Aquí podemos ver también El Tab Bar Item que hemos modificado anteriormente.
    Ahora con la vista seleccionada, en sus propiedades:
    Cambiamos el atributo Background y le ponemos el color que queramos, aquí por ejemplo hemos puesto Azul y Verde, respectivamente.
    Al ejecutar la aplicación se verá lo siguiente:
    Com podemos ver cuando está la primera pestaña seleccionada nos aparece la escena azul. Y cuando pulsamos sobre la segunda pestaña:
    nos aparece la escena verde.

    Eliminando una escena del Tab Bar Controller

    Para eliminar una escena del tab bar controller basta con seleccionar el segue que se une a ella:
    Y eliminarlo. En el storyboard:
    O al intentar volver a ejecutar la aplicación ya no aparecerá esa pestaña:

    Añadir una escena a la Tab Bar

    Para añadir una escena a la Tab Bar es necesario establecer de nuevo el segue en el storyboard, partiendo del tab bar controller y con el control pulsado llevándolo a la escena que queremos incluir y soltarlo allí:
    Al soltarlo debería aparecer un menú contextual:
    Selecionamos dentro de Relationship Segue, view controllers y debería volver a aparecer el segue en su lugar:
    y al ejecutarlo debería aparecer la pestaña nueva:
    Así dentro del Tab Bar Controller podemos incluir varias pestañas. Esto se suele denominar navegación en Anchura. En comparación al Navigation Controller que se suele llamar navegación en Profundidad.
    Prueba a Añadir una nueva vista Roja al Tab Bar Controller.

    Combinando el Tab Bar Controller con el Navigation Controller

    Ahora sobre el proyecto que ya hemos creado vamos a incluir el Navigation Controller, para ver cómo trabajan las dos juntas. Arrastramos al Storyboard un nuevo Navigation Controller:
    Com ya vimos en el apartado de Navigation Controller. Al arrastrarlo nos aparece el Navigation Controller enlazado por un segue con un Table View Controller. De momento lo dejaremos para explicar las posibles combinaciones entre estos dos sistemas de navegación.

    Dejando el Tab Bar Controller delante

    Ahora veamos como funciona cuando enlazamos el Tab Bar Controller con un Navigation Controller. Para ello como vimos anteriormente, arrastramos con el control pulsado desde el Tab Bar Controller hasta el navigation controller y decimos que el segue es de tipo view controllers:
    Nos aparecerá el segue conectando el tab bar controller con el navigation controller y debajo de la escena del navigation controller aparece su respectiva pestaña editable. Por supuesto en el tab bar controller aparecerá esa nueva pestaña:
    Al ejecutar la aplicación podemos ver que al pulsar en la pestaña de la navegación:
    nos sigue saliendo la barra de navegación arriba y la barra de pestañas abajo.
    Repitamos el mismo proceso, pero esta vez colocando el navigation controller entre la tabbar y la vista roja:
    • Incluimos otro Navigation Controller
    • Eliminamos el segundo Table View Controller que está asociado a ese nuevo Navigation Controller
    • Eliminamos el segue que conecta el tab bar controller con la escena roja
    • Conectamos el tabbar controller con el nuevo navigation controller
    • Le damos un título a la pestaña del nuevo navigation controller
    • Y le decimos que la escena roja es la roto view controller del nuevo navigation controller

    Debería quedar algo parecido a esto:

    Ahora vamos a incluir un nuevo view controller en el storyboard y lo enlazaremos con la escena roja mediante un segue de tipo push:

    • Incluimos un nuevo View Controller
    • Le colocamos un color Cyan al view principal de ese nuevo view controller
    • Incluimos un botón en la barra de navegación en la escena roja
    • Arrastramos desde el botón, con el control pulsado hasta la escena Cyan
    • Seleccionamos el tipo push
    Debería quedar de una manera similar a esto:
    Al ejecutar la aplicación y entrar a la pestaña de la segunda navegación veremos lo siguiente:
    como podemos ver nos visualiza la escena roja y se ve el botón que hemos incluido, si lo pulsamos:

    nos sigue saliendo la barra de navegación arriba que nos permite volver a la vista roja y sigue saliendo la barra de pestañas en la parte inferior.

    Licencia Creative Commons

    Si estás interesado en seguir formándote tenemos una serie de cursos gratuitos:

    Cursos Gratuitos

    También disponemos de algunos cursos de pago por si son de tu interés:

    https://cursosdedesarrollo.com/tienda/

    Curso de Angular:

    Angular

     

    Uso de cookies

    Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información. ACEPTAR

    Aviso de cookies