¿Referencia de UITableViewCell al padre UITableView?

¿Hay alguna forma de acceder al UITableView propietario desde una UITableViewCell ?

Almacene una referencia weak a tableView en la celda, que establecería en -tableView:cellForRowAtIndexPath: del -tableView:cellForRowAtIndexPath: de su tabla.

Esto es mejor que confiar en self.superview para que siempre sea exactamente tableView es frágil. Quién sabe cómo Apple podría reorganizar la jerarquía de UITableView de UITableView en el futuro.

Esta es una forma más sencilla de hacerlo, que no depende de ninguna jerarquía particular de UITableView. Funcionará con cualquier versión futura de iOS, siempre que UITableView no cambie el nombre de clase por completo. No solo esto es extremadamente improbable, pero si sucede, tendrá que retocar su código de todos modos.

Solo importe la categoría a continuación y obtenga su referencia con [myCell parentTableView]

 @implementation UIView (FindUITableView) -(UITableView *) parentTableView { // iterate up the view hierarchy to find the table containing this cell/view UIView *aView = self.superview; while(aView != nil) { if([aView isKindOfClass:[UITableView class]]) { return (UITableView *)aView; } aView = aView.superview; } return nil; // this view is not within a tableView } @end 

 // To use it, just import the category and invoke it like so: UITableView *myTable = [myTableCell parentTableView]; // It can also be used from any subview within a cell, from example // if you have a UILabel within your cell, you can also do: UITableView *myTable = [myCellLabel parentTableView]; // NOTE: // If you invoke this on a cell that is not part of a UITableView yet // (ie, on a cell that you just created with [[MyCell alloc] init]), // then you will obviously get nil in return. You need to invoke this on cells/subviews // that are already part of a UITableView. 

ACTUALIZAR
Existe una discusión en los comentarios sobre si mantener una referencia débil es un mejor enfoque. depende de tus circunstancias. Atravesar la jerarquía de vista tiene una pequeña penalización de tiempo de ejecución mientras haces bucles hasta que se identifique la UIView objective. ¿Qué tan profundos son tus puntos de vista? Por otro lado, mantener una referencia en cada celda tiene una penalización mínima de memoria (una referencia débil es un puntero después de todo), y generalmente agregar relaciones de objetos donde no se necesitan se considera una mala práctica de diseño de OO por muchas razones, y debería evitarse (ver detalles en los comentarios a continuación).

Lo que es más importante, mantener las referencias de las tablas dentro de las celdas agrega complejidad al código y puede generar errores, ya que las UITableViewCells son reutilizables. No es coincidencia que UIKit no incluya una propiedad cell.parentTable . Si define el suyo, debe agregar código para administrarlo, y si no lo hace de manera efectiva, puede introducir pérdidas de memoria (es decir, las células viven más allá de la vida útil de su tabla).

Porque normalmente utilizará la categoría anterior cuando un usuario interactúa con una celda (se ejecuta para una sola celda) y no cuando [tableView:cellForRowAtIndexPath:] la tabla en [tableView:cellForRowAtIndexPath:] (se ejecuta para todas las celdas visibles), el tiempo de ejecución el costo debe ser insignificante.

Xcode 7 beta, Swift 2.0

Esto funciona bien para mí, en mi opinión no tiene nada que ver con la jerarquía o lo que sea. No tuve problemas con este enfoque hasta ahora. Lo he usado para muchas devoluciones de llamada asíncronas (por ejemplo, cuando se realiza una solicitud de API).

Clase TableViewCell

 class ItemCell: UITableViewCell { var updateCallback : ((updateList: Bool)-> Void)? //add this extra var @IBAction func btnDelete_Click(sender: AnyObject) { let localStorage = LocalStorage() if let description = lblItemDescription.text { //I delete it here, but could be done at other class as well. localStorage.DeleteItem(description) } updateCallback?(updateList : true) } } 

Clase de vista de tabla interior que implementa DataSource y Delegate

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell: ItemCell = self.ItemTableView.dequeueReusableCellWithIdentifier("ItemCell") as! ItemCell! cell.updateCallback = UpdateCallback //add this extra line cell.lblItemDescription?.text = self.SomeList[indexPath.row].Description return cell } func UpdateCallback(updateTable : Bool) //add this extra method { licensePlatesList = localStorage.LoadNotificationPlates() LicenseTableView.reloadData() } 

Por supuesto, puedes poner cualquier variable en la updateCallback y cambiar su función en la tableView consecuencia.

Sin embargo, alguien podría querer decirme si es seguro de usar, solo para estar seguro.

Debe agregar una referencia a UITableView cuando construye la celda de vista de tabla.

Sin embargo, casi seguramente lo que realmente quiere es una referencia a su UITableViewController … que requiere lo mismo, configúrelo como un delegado de la celda cuando construya la celda y entréguela a la vista de tabla.

Un enfoque alternativo si está conectando acciones es construir las celdas en IB, con el controlador de vista de tabla como el propietario de los archivos, luego conecte los botones de la celda a las acciones en el controlador de vista de tabla. Cuando cargue el xib de la celda con loadNibNamed, pase el controlador de la vista como propietario y las acciones del botón volverán a conectarse al controlador de la vista de tabla.

Si tiene clases personalizadas para su UITableViewCells, puede agregar una variable de tipo id en el encabezado de su celda y sintetizar la variable. Después de configurar la variable cuando carga la celda, puede hacer lo que quiera con la vista de tabla o cualquier otra vista superior sin demasiados problemas o gastos generales.

cell.h

  // interface id root; // propery @property (nonatomic, retain) id root; 

cell.m

@synthesize root;

tableviewcontroller.m

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // blah blah, traditional cell declaration // but before return cell; cell.root = tableView; } 

Ahora puede llamar a cualquiera de los métodos de la tabla desde dentro de su celda usando la variable raíz. (por ejemplo, [root reloadData]);

Ah, me lleva de vuelta a los buenos tiempos de la progtwigción flash.

Los dos métodos en otras respuestas son: (A) almacenar una referencia a la tabla, o (B) caminar por las supervistas.

Siempre usaría algo como (A) para objetos modelo y (B) para celdas de tabla.

Células

Si está tratando con una UITableViewCell, entonces AFAIK debe tener a mano el UITableView (digamos que está en un método de delegado de tabla), o está tratando con una celda visible que está en la jerarquía de vista. De lo contrario, es posible que esté haciendo algo mal (tenga en cuenta el “bien”).

Las células se reutilizan generosamente y si tiene una que no es visible, entonces la única razón real por la que existe es debido a la optimización del rendimiento de iOS UITableView (una versión más lenta de iOS se habría lanzado y con suerte desasoció la celda cuando se movió fuera de la pantalla ) o porque tiene una referencia específica al mismo. Supongo que esta es probablemente la razón por la que las celdas de la tabla no están dotadas de un método de instancia tableView.

Así que (B) da el resultado correcto para todos los iOS hasta el momento, y todos los futuros hasta que cambien radicalmente la forma en que funcionan las vistas.

Aunque para evitar escribir código generalizable una y otra vez, usaría esto:

 +(id)enclosingViewOfView:(UIView*)view withClass:(Class)returnKindOfClass { while (view&&![view isKindOfClass:returnKindOfClass]) view=view.superview; return(view); } 

y un método de conveniencia:

 +(UITableView*)tableForCell:(UITableViewCell*)cell { return([self enclosingViewOfView:cell.superview withClass:UITableView.class]); } 

(o categorías si lo desea)

Por cierto, si le preocupa el efecto de un ciclo con 20 o más iteraciones de ese tamaño en el rendimiento de su aplicación, no lo haga.

Modelos

Si está hablando del objeto modelo que se muestra en la celda, definitivamente ese modelo podría / debería saber sobre su modelo principal, que puede usarse para encontrar o activar cambios en la (s) tabla (s) que el modelo de la celda podría se mostrará en. Esto es como (A), pero menos frágil con futuras actualizaciones de iOS (por ejemplo, un día podrían hacer que la caché de reutilización UITableViewCell exista por reuseidentifier, en lugar de por reuseidentifier por tableview, en ese día todas las implementaciones que usan el débil el método de referencia se romperá).

El método del modelo Th se usaría para cambios en los datos mostrados en la celda (es decir, cambios del modelo) ya que los cambios se propagarán donde se muestre el modelo (por ejemplo, algún otro UIViewController en otra parte de la aplicación, registro, …)

El método de celda se usaría para acciones de vista de tabla, lo que probablemente siempre sería una mala idea si la celda no es siquiera una subvista de una tabla (aunque es su código, se vuelven locos).

De cualquier manera, use una prueba unitaria en lugar de asumir que el código aparentemente más limpio solo funciona cuando actualiza iOS.

 UITableView *tv = (UITableView *) self.superview.superview; UITableViewController *vc = (UITableViewController *) tv.dataSource;