Tablas en iOS: celdas con iOSCustomTableCell

iOSCustomTableCellCon Xojo 2016r2 se han incrementado notablemente las capacidades a la hora de crear y desplegar aplicaciones nativas iOS (iPhone, iPad y iPod touch); y una de las parcelas en las que se reflejan dichas mejoras es en uno de los controles de UI más utilizados en cualquier aplicación: las tablas. Ahora es posible reordenarlas, editarlas… ¡y también utilizar celdas personalizadas con iOSCustomTableCell! A continuación te cuento como.

A partir de Xojo 2016r2 podemos utilizar en nuestras tablas tantas celdas personalizadas como deseemos, ¡e incluso combinar varias celdas personalizadas en una misma tabla! La libertad de utilizar celdas personalizadas es que estas podrán contener cualquier combinación de controles y elementos en sí mismas, ampliando así notablemente la representación de información más allá de una simple etiqueta de texto y/o imagen o casilla de verificación.

iOSCustomTableCell: diseña tus celdas personalizadas

El diseño de las celdas personalizadas en las aplicaciones iOS es posible gracias a la disponibilidad de la nueva clase iOSCustomTableCell y que podemos añadir a nuestro proyectos tal y como haríamos en el caso de cualquier otro control, simplemente arrastrándolo desde la Biblioteca hacia el Navegador de Proyecto (la columna situada más a la izquierda en el IDE).

Como resultado, crearemos una subclase cuya clase superior será iOSCustomTableCell y sobre la que podremos añadir código en los eventos Open y Close, así como definir o acceder a la información correspondiente en las propiedades expuestas: Visible, AccessibilityHint y AccessibilityLabel.

iOS Custom Table Cell

En cuanto a la parte visual, y si ya estás acostumbrado a trabajar con los ContainerControl en las aplicaciones Xojo Desktop (OS X, Windows y Linux), entonces encontrarás que las clases derivadas de iOSCustomTableCell proporcionan en cierto modo la misma funcionalidad: una vista, lienzo o “espacio” sobre el cual puedes añadir y disponer cualquier otro de los controles UI disponible, incluyendo aquellos diseñados por nosotros mismos.

Al seleccionar cualquiera de las subclases añadidas al proyecto accederemos al conocido Editor de Diseño, sobre el cual podemos ajustar el tamaño de vista propiamente dicho para nuestra iOSCustomTableCell y también disponer del resto de controles tal y como deseemos presentar la información en nuestras tablas. Por supuesto, cualquiera de los controles añadidos responderá a los eventos ejecutando el código asociado.

Edición de diseño para un iOSCustomTableCell

 

Pintar las celdas en la tabla

Como se ha visto, el diseño de las celdas personalizadas no plantea ningún problema. Ahora bien, ¿cómo podemos indicar a la tabla cuál de las celdas personalizadas queremos utilizar en cada caso, además de actualizar la información propiamente dicha para cada uno de los controles incluidos en las celdas? La respuesta se encuentra en la interface de clase iOSTableDataSource cuya implementación ya se pudo ver en una entrada anterior del blog.

Es decir, si bien podemos trabajar con las celdas personalizadas añadiéndolas manualmente desde código, lo más eficiente consiste en definir un objeto que actúe como fuente de datos y que sea interrogado por la propia tabla cada vez que esta requiera el pintado de una celda en concreto. Esta orientación es realmente mejor desde el punto de vista de la OOP (programación orientada a objetos), donde nuestra clase —actuando como proveedora de información— adopta un papel pasivo y ejecutando el código sólo en los casos en los que sea preciso.

Dicho enfoque también es más eficiente en cuanto a la gestión de los recursos consumidos por la tabla propiamente dicha, ¡ya que esta reutilizará la misma celda siempre que sea posible! Esto significa, por tanto, que cada vez que la tabla nos solicite la devolución de una nueva celda hemos de asegurarnos de actualizar correctamente todos los controles de la celda personalizada. De lo contrario, es probable que una celda mostrase algún dato asociado a cualquier celda anterior.

Tal y como vimos en su día, cuando añadimos la interfaz iOSTableDataSource a una clase hemos de implementar obligatorio los métodos RowCount, RowData, SectionCount y SectionTitle. En definitiva, estos son los métodos que invocará la tabla cada vez que necesite consultar información para su dibujado.

De entre todos estos métodos, el que nos interesa particularmente para utilizar las celdas personalizadas es RowData; es decir, el invocado por la tabla cada vez que necesita dibujar una nueva celda. De hecho, puedes comprobar que en la signatura de dicho método recibiremos como argumentos una variable que apunta a la tabla propiamente dicha, así como el valor entero de la sección bajo la cual se va a pintar la celda y también el número entero de la fila (celda) que se va a pintar. El método espera que le devolvamos, por tanto, una instancia de iOSTableCellData como resultado.

¿Cómo obtenemos una instancia de iOSTableCellData a partir de nuestro control personalizado iOSCustomTableCell? La respuesta se encuentra en el método CreateCustomCell de la clase iOSTable. Dicho método espera que le pasemos como parámetro la información de Tipo correspondiente a nuestro control, algo que podemos lograr ejecutando la siguiente instrucción de código:

GetTypeInfo(MyCustomCell)

Donde “MyCustomCell” se correspondería con una subclase de iOSCustomTableCell que hayamos añadido al proyecto. Por tanto, la instrucción completa para obtener la iOSTableCellData propiamente dicha sería:

dim cell as iOSTableCellData = table.CreateCustomCell(GetTypeInfo(MyCustomCell))

Acceder a los controles de una iOSCustomTableCell

Ahora bien, al ejecutar la anterior línea de código obtendremos una variable que apunta a una instancia de iOSTableCellData… y eso significa que no podríamos acceder a los controles específicos que hubiésemos definido sobre nuestra clase iOSCustomTableCell. ¿Cómo solucionamos el problema? La respuesta está en la proyección de clases (o Cast).

La proyección de clases consiste en indicar al compilador que deseamos utilizar una instancia de una clase determinada como si fuese de otra. Esto supone un riesgo importante en tiempo de ejecución si no estamos seguros de que la clase sobre la cual deseamos realizar la proyección “encierra” en realida la estructura de objeto correspondiente a la clase sobre la que deseamos trabajar.

En este caso nosotros sabemos con certeza el nombre de las clases que hemos definido como iOSCustomTableCell, y que, de hecho, hemos utilizado su Información de Tipo para generar una instancia de iOSTableCellData. Por tanto, no ningún problema en realizar la proyección de clase y almacenar el resultado en una nueva variable, ahora sí, como una instancia de la celda de personalizada que hemos creado. Para ello, hemos de realizar el cast sobre el objeto apuntado por la popiedad Control de la instancia iOSTableCellData:

dim CustomCell as MyCustomCell = MyCustomCell(cell.Control)

A partir de aquí ya utilizaríamos nuestro objeto DataSource en combinación con los controles embebidos en la instancia de nuestra celda personalizada, apuntada por la variable “CustomCell” en este ejemplo, para actualizar toda la información que deseemos dibujar en la celda ¡y listo!

Una vez finalizado, sólo tendremos que devolver el resultado con un sencillo:

return cell

¿Tienes dudas sobre cualquiera de los términos utilizados en este tutorial? Recuerda que en el eBook “Programación Multiplataforma Xojo” se explica esto y mucho más ¡desde cero! para que aprendas a crear programas multiplataforma con el lenguaje de programación Xojo a tu ritmo y sin conocimientos previos de programación.

Related Posts / Entradas Relacionadas

Un comentario en “Tablas en iOS: celdas con iOSCustomTableCell

  1. iOS: Selección de Imágenes y Acceso a cámara - AprendeXojo

    […] crear para su uso en cualquier instancia de una Tabla (iOSTable). Por tanto, te recomiendo que leas dicha entrada para refrescar los conceptos en el caso de que lo veas necesario. A continuación nos limitaremos a […]

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *