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: Manejo de formularios (II): UISwitch, UISlider, UISegmentedControl, UIStepper y UIDatePicker

    Veamos ahora más vistas que podemos usar en los formularios. Recordemos que todos ellos deberán utilizarse como IBOutlets y para manejar sus eventos deberemos utilizar las IBAction, tal como dijimos en el tema de IBOutlets y UIActions.

    UISwitch: la checkbox

    Típicamente las checkbox de han utilizados como mecanismos que pueden ser activados o desactivados por parte del usuario, para marcar una opción.
    En este caso el UISwitch actua de una manera similar. Por lo que cuando lo incluyamos como un IBOutlet podremos gestionar el objeto que tenemos en la vista y consultar su estado.
    Veamos sus atributos en el inspector:
    Como se puede ver la parte más importante es el estado que puede estar en On u Off. Si lo dejamos en On aparecerá marcado por defecto, con Off sucederá lo contrario.
    También podemos llegar a seleccionar una imagen para el estado On y otra para el Off.

    Propiedades: on

    La propiedad más importante del UISwitch es la llama on de tipo booleano. Así que si queremos que esté activado por defecto mediante código deberemos realizar lo siguiente:
    check.on=YES;
    En el ejemplo usaremos el objeto IBOutlet llamado check.

    Eventos

    El evento más importante para el UISwitch es el Value Changed. Es el que nos permitirá saber cuando haya sido cambiado si estado. Y se disparará tantas veces como el usuario haya cambiado su valor.
    Pongamos un ejemplo de IBAction:
    – (IBAction)checkPulsada:(id)sender {
        NSLog(@”Check pulsado:%hhd”,[check isOn]);
    }
    Como puede verse en el ejemplo estamos consultado el método isOn que es el getter de la propiedad on.

    UISlider: el selector numérico de rango

     Este tipo de control en el formulario permite seleccionar de un rango de números un valor.

    Atributos: value

    Veamos sus atributos para que resulte más fácil explicarlo:
    Como podemos ver tenemos varios atributos importantes:
    • value: es el valor que ha seleccionado el usuario, de tipo float.
    • value minimum: es el valor mínimo del rango
    • value maximum: es el valor máximo que puede tomar
    • value Current: es el valor del que va a partir
    • Update Events, Continuous: cuando está seleccionado permite que se vaya cambiando el valor según el usuario vaya moviendo el slider. Si no está marcado, sólo se disparará cuando el usuario haya dejado de mover el slider.
    En el ejemplo tenemos la típica selección de edad, 18 el mínimo, 65 el máximo y el valor actual es de 35.

    Eventos: Value Changed

    De cara a ver su funcionamiento en el ejemplo hemos dado de alta un UISlider con esas configuraciones y un TextLabel, ambos con sus respectivos IBOutlet, slider y edad, respectivamente.
    También hemos dado de alta un IBAction llamado cambiaSlider: que será llamado cada vez que cambie el valor del slider, es decir relacionado con el Evento Value Changed, veamos la implementación del método:
    – (IBAction)cambiaSlider:(id)sender {
        edad.text=[NSString stringWithFormat:@”%.0f”,slider.value];
    }
    Si nos damos cuenta el valor del slider es de tipo float, por lo que al convertirlo en cadena de caracteres utilizamos el %.0f  que nos permite pasarlo a un número sin decimales.
    Luego se lo asignamos al texto del TextLabel de la edad para ver como va cambiando el valor del slider.

    UISegmentedControl: los radio button

    Como en la mayor parte de los formularios necesitamos presentar varias opciones de las cuales sólo podamos seleccionar una. Los radio button de HTML en iOS se llaman UISegmentedControl.

    Atributos

    Como podemos ver tenemos varios elementos interesantes. Para empezar el número de segmentos. Este nos permitirá meter más elementos en el siguiente desplegable.
    Una vez seleccionad un segmento en el desplegable podemos configurar un título, una imagen y si está habilitado o seleccionado de primeras.
    En el ejemplo tenemos dos segmentos para hombre y mujer y el primer segmento, el segmento 0, nos aparecerá seleccionado.
    De esta manera si queremos saber que segmento ha sido seleccionado por el usuario deberemos usar el método   selectedSegmentIndex:
    [sexo selectedSegmentIndex]
    Este método nos devolverá un número del segmento que ha sido seleccionado por parte del usuario, empezando por 0.En el ejemplo, tenemos dos segmentos: 0 corresponde a Hombre y 1 a Mujer.
    Si quisiéramos averiguar el título asignado a un segmento deberemos utilizar el método titleForSegmentAtIndex:
    [sexo titleForSegmentAtIndex:@0]
    En este caso nos devolverá la cadena de caracteres Hombre.

    Eventos: Value Changed

    Como en otros casos disponemos de un evento Value Changed que nos permite ejecutar un IBAction cada vez que cambie el segmento seleccionado, veamos un ejemplo:
    – (IBAction)cambiaSegmented:(id)sender {
        NSLog(@”Sexo seleccionado:%ld”,(long)[sexo selectedSegmentIndex]);
    }
    En este caso mostrará por consola el valor 0 o 1 dependiendo de lo que haya seleccionado el usuario.

    UIStepper: pasito a pasito

    En muchos formularios queremos que el usuario vaya cambiando un valor pulsando botones para evitar que tenga que introducir manualmente un número.

    Atributos: value

    Como podemos ver es muy similar al UISlider, en su funcionamiento básico. El atributo principal será value. Minimum, Maximum y Current funcionan como con el UISlider.
    Sin embargo Step nos permitirá cambiar el incremento y del decremento del valor almacenado.
    Así si colocamos un Step de 2, sumará o restará 2 al valor cuando pulsemos el más o el menos respectivamente.
    Continuous funcionará de una manera parecida al Slider también.
    Y el Autorepeat permitirá dejar pulsado un botón y que se repita la acción pasado un tiempo.

    UIDatePicker: El selector de fecha y hora

    Este tipo de selector permitirá darle a escoger al usuario una fecha y una hora.

    Atributos

    Como podemos ver tenemos:
    • date: nombre del atributo de tipo NSDate que almacena la fecha
    • Mode: permite escoger el tipo de dato a recoger
    • Interval: el intervalo de tiempo
    • Date: fecha que queremos coger por defecto
    • Minimum y Maximum Date: fecha mínima y máximo
    • Timer: tiempo que queremos dar para escoger la fecha

    Eventos: Value Changed

    Como en el resto de elementos de formulario podemos escoger eventos para realizar un IBAction, el típico es Value Changed. Veamos un ejemplo:

    – (IBAction)cambiaPicker:(id)sender {
        NSLog(@”%@”,datepicker.date);
    }
    Licencia Creative Commons

    Suscríbete al Boletín

    Si quieres estar al tanto de las novedades del blog, ya sabes :)
    * = campo obligatorio

    powered by MailChimp!

    Archivos

    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