71 votes

Référence de UITableViewCell au parent UITableView?

Existe-t-il un moyen d'accéder à UITableView à partir d'un UITableViewCell? (si la cellule appartient à cette table?

125voto

jbrennan Points 7307

Il est probablement préférable de stocker dans la cellule une référence weak à la table, que vous auriez définie dans -tableView:cellForRowAtIndexPath: de la source de données de votre table. C’est mieux parce que compter sur self.superview pour toujours être exactement à la table est fragile. Qui sait comment Apple pourrait réorganiser la hiérarchie de vues de UITableView à l'avenir.

18voto

DTs Points 326

Voici une jolie manière de faire, qui ne repose pas sur une UITableView hiérarchie. Il fonctionne avec toutes les futures version d'iOS, à condition qu' UITableView ne change pas d'un nom de classe tout à fait. Non seulement c'est extrêmement rare, mais si cela arrive, vous aurez à retoucher votre code de toute façon.

Il suffit d'importer la catégorie ci-dessous et obtenez votre référence en [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
// (i.e., 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.


Mise à JOUR
Il y a une discussion dans les commentaires si en gardant une référence faible est une meilleure approche. Il dépend de votre situation. Traversant le point de vue de la hiérarchie a quelques petits exécution de la pénalité que vous êtes en boucle jusqu'à ce que la cible UIView est identifié. Quelle est la profondeur est votre point de vue? D'autre part, de garder une référence sur chaque cellule a une mémoire minimale de pénalité (une référence faible est un pointeur, après tout), et généralement en ajoutant les relations d'objet où ils ne sont pas nécessaires est considéré comme un mauvais OO pratique de conception pour de nombreuses raisons, et doit être évitée (voir les détails dans les commentaires ci-dessous).

Plus important encore, en gardant la table de références à l'intérieur des cellules ajoute la complexité du code et peut conduire à des erreurs, car UITableViewCells sont réutilisables. C'est pas par hasard que l' UIKit n'inclut pas un cell.parentTable de la propriété. Si vous définissez votre propre, vous devez ajouter du code pour gérer ça, et si vous ne parvenez pas à le faire de manière efficace, vous pouvez introduire des fuites de mémoire (c'est à dire, les cellules de vivre au-delà de la durée de vie de leur table).

Parce que typiquement, vous allez être en utilisant la catégorie ci-dessus lorsqu'un utilisateur interagit avec une cellule (execute pour une seule cellule), et non pas lors de la pose de la table en [tableView:cellForRowAtIndexPath:] (exécution pour toutes les cellules visibles), le moteur d'exécution coût devrait être négligeable.

7voto

Vous devez ajouter une référence à la UITableView lorsque vous construisez la vue de la table de la cellule.

Cependant, presque certainement ce que vous voulez vraiment est une référence à votre UITableViewController... qui exige la même chose, de le définir comme un délégué de la cellule lorsque vous générez de la cellule et de le remettre à la vue de la table.

Une autre approche si vous êtes le câblage en place des actions est de renforcer les cellules de l'IB, avec le table view controller comme les fichiers propriétaire - puis fil des boutons dans la cellule à des actions dans le table view controller. Lorsque vous chargez la cellule xib avec loadNibNamed, passer de l'avis du contrôleur en tant que propriétaire et le bouton actions seront connectés à la table view controller.

1voto

wils Points 1

Les deux méthodes dans d'autres réponses sont: (A) stocker une référence à la table, ou (B) marcher jusqu'à la superviews.

J'avais toujours utiliser quelque chose comme (A) pour les objets de modèle et (B) pour les cellules de tableau.

Les cellules

Si vous faites affaire avec un UITableViewCell, alors autant que je sache, vous devez soit avoir la UITableView à la main (dire que vous êtes dans une table délégué de la méthode), ou de traiter avec une cellule visible qui est dans la vue de la hiérarchie. Sinon, vous pourriez bien être en train de faire quelque chose de mal (veuillez noter que le "peut").

Les cellules sont généreusement réutilisés et si vous en avez un qui n'est pas visible, alors la seule vraie raison de cette cellule existe, c'est parce que de iOS UITableView l'optimisation de la performance (un ralentissement de la version iOS aurait publié et, espérons-le dealloc avais la cellule quand il a déménagé hors de l'écran) ou que vous avez une référence spécifique. Je suppose que c'est probablement la raison pour laquelle les cellules d'un tableau qui ne sont pas doués avec un tableView méthode d'instance.

(B) donne les meilleurs résultats pour tous les iOS et tous ceux à venir jusqu'à ce qu'ils changent radicalement la manière dont les vues de travail.

Mais afin d'éviter d'écrire généralisables d'un code, j'utilise ceci:

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

et une méthode de convenance:

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

(ou catégories si vous le souhaitez)

BTW, si vous êtes préoccupé par l'effet d'une boucle avec 20 itérations de cette taille sur vos performances de l'application,.. ne l'est pas.

Modèles

Si vous parlez du modèle objet qui s'affiche dans la cellule, puis définitivement ce modèle pourrait/devrait savoir à propos de sa mère modèle, qui peut être utilisé pour trouver, ou de déclencher des changements dans, les table(s) de la cellule peuvent être affichés. C'est comme (Un), mais moins fragile avec l'avenir, les mises à jour iOS (par exemple, un jour, ils pourraient faire la UITableViewCell réutilisation cache exister par reuseidentifier, plutôt que par reuseidentifier par tableview, ce jour-là toutes les implémentations qui utilisent la faiblesse de la méthode de référence va casser).

Th modèle de la méthode utilisée pour la modification des données affichées dans la cellule (c'est à dire les changements de modèle) étant donné que les changements se propagent partout où le modèle est affiché (par exemple. certains autres UIViewController quelque part d'autre dans l'application, l'exploitation forestière, ...)

La cellule de la méthode utilisée pour tableview actions, qui devrait toujours être une mauvaise idée si la cellule n'est même pas une sous-vue d'un tableau (même si c'est votre code, aller de noix).

De toute façon, l'utilisation d'un test de l'unité plutôt que de supposer que, apparemment, nettoyeur de code fonctionne, tout simplement lors de la mise à jour de iOS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X