¿Qué encontrarás en este post?
ToggleCómo mantener sincronizados una UITableViewCell y su modelo
En un UINavigationController tenía puesto un UITableView con una serie de celdas: 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: 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“.