UITableView antes

Mantener sincronizados una UITableViewCell y su modelo

Cómo mantener sincronizados una UITableViewCell y su modelo

En un UINavigationController tenía puesto un UITableView con una serie de celdas:

UITableView antes

Al hacer clic sobre alguna de las UITableViewCells, se carga una nueva UIView sobre el UINavigationController para editar, entre otras cosas, el texto de la celda.

Ahora, al eliminar esa UIView y volver a la UITableView, me encuentro con la siguiente situación:

UITableViewAfter

Es decir, el nombre, al haber aumentado de tamaño, pasa a ser visualizado «recortado» y con tres puntos suspensivos.  Por lo visto, una vez creada la UITableViewCell, se resiste a  modificar el tamaño de su UITextLabel.

Notificar a UITableViewCell del cambio

Lo primero es que mi UITableViewCell sea notificada del cambio. La solución más sencilla, es que la UIView usada para editar el texto tenga un delegate y que notifique a éste del cambio. Entonces basta con que la UITableViewCell implemente el protocolo en cuestión.

Cómo cambiar el tamaño de la UITextLabel

Suponiendo que hemos sido notificados del cambio, la forma más sencilla y cutre sería hacer un [self reloadData]. No es lo más eficiente que digamos.

Una segunda opción, sería hacer un [cell.textLabel sizeToFit] (sizeToFit es un mensaje que entienden todas las UIViews, y que en general suele funcionar). Sin embargo, estamos aumentando los puntos del código donde se modifica el «layout» de las celdas, lo que puede generar confusión en el futuro.

reloadRowsAtIndexPaths:withRowAnimation: al rescate

Una tercera opción, que evita desperdigar el código de «layout» y que no implica en volver a cargar todas las celdas visibles es:

-(void) editTaskViewController:(FRREditTaskViewController *)sender
          didChangeNameForTask:(FRRFlatTask *)aTask{    

    NSIndexPath *idx = [NSIndexPath indexPathForRow:[self.pendings indexOfObject:aTask]
                                          inSection:0];
    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:idx]
                          withRowAnimation:UITableViewRowAnimationNone];
}

De esta forma, sólo volvemos a cargar lo que realmente ha cambiado.

Uso de delegates en UITableViewController y sus problemas

El uso de delegates para mantener toda la UITableView en sincronía con todas las partes de su modelo hace con que tu UITableViewController, que de por sí ya es bastante grande, vaya aumentando cada vez más. Poco a poco, la clase termina haciendo y controlando demasiadas cosas, estando casi toda la «inteligencia» de la aplicación concentrada en un objeto, en vez de estar uniformemente distribuida por todos los objetos.

UITableViewController es una chapuza

Es decir, estamos ante un caso claro del «God Class problem«, que describe Arthur Riel en «Object Oriented Design Heuristics«.

Quitarle responsabilidades a UITableViewController y repasarlas a otros MVCs

Una forma de mejorar el diseño, sería subclasificar UITableViewCell creando una clase TaskTableViewCell. Dicha clase observaría, mediante KVO, a un objeto Task que se le pasaría al inicializarla y se encargaría de adaptar su propio «layout» de forma «automágica».

De esta forma, eliminamos la necesidad de tanto delegado  y repasamos las responsabilidades desde el UITableViewController a quién realmente le corresponde.

Conclusión

La implementación que proporciona Apple del UITableViewController definitivamente no me gusta. Padece de varias problemas que se hacen cada vez más hirientes a medida que vas añadiendo tablas a una app:

  • El código de generar y reaprovechar celdas es muy repetitivo y primitivo .
  • Fomenta el «God Object Problem«.

Al ir añadiendo más y más protocolos de delegados, su implementación termina siendo más larga que un día sin internet y con la suegra.

En cuanto tenga algo de tiempo y me ponga un poco más con KVO intentaré buscar alguna solución más eficiente y elegante. Sospecho que pasa por redistribuir las responsabilidades que hoy sólo son de UITableViewCellController entre otras clases, así como una manita de Key Value Observing.

 

Fernando Rodríguez

Sígueme en twitter.
Cursos de desarrollo iPhone

Acerca de Fernando Rodriguez

Fundador & Editor Jefe de justcodeit, Fernando Rodríguez (@frr149 & Linkedin) es desarrollador & un experto en la enseñanza de máxima calidad en programación y desarrollo para dispositivos iOS, Cocoa Touch, Objective C, Swift, Python, entre otros, aunque su mejor carta de presentación, es la opinión de sus alumnos: http://keepcoding.io/es/testimonio/ CLO en KeepCoding & Arunovo. Instructor de iOS Avanzado del Big Nerd Ranch. Profesor Asociado de la U-tad, autor invitado de revistas como iPhoneWorld, Applesfera.com & ponente habitual en conferencias dentro y fuera de España (iOSDevUK, CodeMotion, BCNDevCon, etc). En sus vidas anteriores fue un nerd de Python y Django, mago de Smalltalk, y para su pesar, galeote de C++ y un gran cocinero.

Share this:

Leave a comment