J'ai une vue de table avec des boutons et je veux utiliser l'indexpath.row lorsque l'un d'eux est touché. C'est ce que j'ai actuellement, mais c'est toujours 0
var point = Int()
func buttonPressed(sender: AnyObject) {
let pointInTable: CGPoint = sender.convertPoint(sender.bounds.origin, toView: self.tableView)
let cellIndexPath = self.tableView.indexPathForRowAtPoint(pointInTable)
println(cellIndexPath)
point = cellIndexPath!.row
println(point)
}
swift
button
touch
nsindexpath
Vincent
la source
la source
Réponses:
giorashc l'a presque eu avec sa réponse, mais il a oublié le fait que les cellules ont une
contentView
couche supplémentaire . Ainsi, nous devons aller plus loin:En effet, dans la hiérarchie des vues, une tableView a des cellules en tant que sous-vues qui ont ensuite leurs propres `` vues de contenu '', c'est pourquoi vous devez obtenir la vue de supervision de cette vue de contenu pour obtenir la cellule elle-même. En conséquence, si votre bouton est contenu dans une sous-vue plutôt que directement dans la vue de contenu de la cellule, vous devrez aller autant de couches plus profondes pour y accéder.
Ce qui précède est une de ces approches, mais pas nécessairement la meilleure approche. Bien qu'il soit fonctionnel, il suppose des détails sur un
UITableViewCell
qu'Apple n'a jamais nécessairement documenté, comme sa hiérarchie de vues. Cela pourrait être changé dans le futur, et le code ci-dessus pourrait bien se comporter de manière imprévisible en conséquence.En raison de ce qui précède, pour des raisons de longévité et de fiabilité, je recommande d'adopter une autre approche. Il existe de nombreuses alternatives répertoriées dans ce fil, et je vous encourage à lire, mais mon préféré est le suivant:
Maintenez une propriété d'une fermeture sur votre classe de cellule, demandez à la méthode d'action du bouton de l'appeler.
Ensuite, lorsque vous créez votre cellule dans
cellForRowAtIndexPath
, vous pouvez attribuer une valeur à votre fermeture.En déplaçant votre code de gestionnaire ici, vous pouvez tirer parti de l'
indexPath
argument déjà présent . C'est une approche beaucoup plus sûre que celle répertoriée ci-dessus car elle ne repose pas sur des traits non documentés.la source
Mon approche à ce genre de problème consiste à utiliser un protocole délégué entre la cellule et la tableview. Cela vous permet de conserver le gestionnaire de boutons dans la sous-classe de cellules, ce qui vous permet d'affecter le gestionnaire d'actions de retouche à la cellule prototype dans Interface Builder, tout en conservant la logique du gestionnaire de boutons dans le contrôleur de vue.
Cela évite également l'approche potentiellement fragile de la navigation dans la hiérarchie des vues ou l'utilisation de la
tag
propriété, qui pose des problèmes lorsque les index de cellules changent (à la suite de l'insertion, de la suppression ou de la réorganisation)CellSubclass.swift
ViewController.swift
la source
buttonTapped
est la fonction de délégué et se trouve dans le contrôleur de vue. Dans mon exemple,someButtonTapped
est la méthode d'action dans la cellule@IBAction func someButtonTapped(sender: UIButton) { self.delegate?.buttonTapped(self) }
UPDATE : Obtention de l'indexPath de la cellule contenant le bouton (à la fois section et ligne):
Utilisation de la position du bouton
À l'intérieur de votre
buttonTapped
méthode, vous pouvez saisir la position du bouton, la convertir en coordonnée dans la tableView, puis obtenir l'indexPath de la ligne à cette coordonnée.REMARQUE : parfois, vous pouvez exécuter dans un cas de bord lorsque l'utilisation de la fonction
view.convert(CGPointZero, to:self.tableView)
entraîne la recherchenil
d'une ligne à un point, même s'il existe une cellule tableView. Pour résoudre ce problème, essayez de passer une coordonnée réelle légèrement décalée par rapport à l'origine, telle que:Réponse précédente: Utilisation de la propriété de balise (ne renvoie que la ligne)
Plutôt que de grimper dans les arbres de supervision pour attraper un pointeur vers la cellule qui contient l'UIButton, il existe une technique plus sûre et plus reproductible utilisant la propriété button.tag mentionnée par Antonio ci-dessus, décrite dans cette réponse et illustrée ci-dessous:
Dans
cellForRowAtIndexPath:
vous définissez la propriété de balise:Ensuite, dans la
buttonClicked:
fonction, vous référencez cette balise pour saisir la ligne de l'indexPath où se trouve le bouton:Je préfère cette méthode car j'ai trouvé que se balancer dans les arbres de supervision peut être un moyen risqué de concevoir une application. Aussi, pour l'objectif-C, j'ai utilisé cette technique dans le passé et j'ai été satisfait du résultat.
la source
indexPath.section
en plus deindexPath.row
(sans réinitialiser la propriété de la balise en tant queindexPath.section
),cellForRowAtIndexPath:
vous pouvez simplement changer la balise enbutton.tag = indexPath
, puis dans labuttonClicked:
fonction, vous pouvez accéder à la fois en utilisantsender.tag.row
etsender.tag.section
.Utilisez une extension pour UITableView pour récupérer la cellule pour n'importe quelle vue:
La réponse de @ Paulw11 sur la configuration d'un type de cellule personnalisé avec une propriété de délégué qui envoie des messages à la vue tableau est une bonne solution, mais elle nécessite un certain travail de configuration.
Je pense que parcourir la hiérarchie des vues de la cellule de vue tableau à la recherche de la cellule est une mauvaise idée. Il est fragile - si vous enfermez ultérieurement votre bouton dans une vue à des fins de mise en page, ce code est susceptible de se casser.
L'utilisation des balises de vue est également fragile. Vous devez vous rappeler de configurer les balises lorsque vous créez la cellule, et si vous utilisez cette approche dans un contrôleur de vue qui utilise des balises de vue à une autre fin, vous pouvez avoir des numéros de balise en double et votre code peut ne pas fonctionner comme prévu.
J'ai créé une extension à UITableView qui vous permet d'obtenir l'indexPath pour toute vue contenue dans une cellule de vue de table. Il renvoie un
Optional
qui sera nul si la vue transmise ne fait pas partie d'une cellule de vue de tableau. Vous trouverez ci-dessous le fichier source de l'extension dans son intégralité. Vous pouvez simplement placer ce fichier dans votre projet, puis utiliser laindexPathForView(_:)
méthode incluse pour rechercher l'indexPath qui contient n'importe quelle vue.Pour l'utiliser, vous pouvez simplement appeler la méthode dans IBAction pour un bouton contenu dans une cellule:
(Notez que la
indexPathForView(_:)
fonction ne fonctionnera que si l'objet de vue qui lui est transmis est contenu dans une cellule actuellement à l'écran. C'est raisonnable, car une vue qui n'est pas à l'écran n'appartient pas réellement à un indexPath spécifique; il est probable que être affecté à un indexPath différent lorsqu'il contient une cellule recyclée.)ÉDITER:
Vous pouvez télécharger un projet de démonstration fonctionnel qui utilise l'extension ci-dessus à partir de Github: TableViewExtension.git
la source
Pour
Swift2.1
J'ai trouvé un moyen de le faire, j'espère que cela aidera.
la source
Vous avez un bouton (myButton) ou toute autre vue dans la cellule. Attribuez une balise dans cellForRowAt comme ceci
Maintenant, dans vous appuyez sur Fonction ou tout autre. Récupérez-le comme ceci et enregistrez-le dans une variable locale.
Après cela, vous pouvez utiliser n'importe où ce currentCellNumber pour obtenir le indexPath.row du bouton sélectionné.
Prendre plaisir!
la source
Dans Swift 4, utilisez simplement ceci:
la source
tableView
s'agit d'une variable de sortie qui doit être référencée avant que cette réponse ne fonctionne.Très simple obtention du chemin d'indexation rapide 4, 5
Comment obtenir IndexPath Inside Btn Click:
la source
Étant donné que l'expéditeur du gestionnaire d'événements est le bouton lui-même, j'utiliserais la
tag
propriété du bouton pour stocker l'index, initialisé danscellForRowAtIndexPath
.Mais avec un peu plus de travail, je ferais d'une manière complètement différente. Si vous utilisez une cellule personnalisée, voici comment j'aborderais le problème:
cellForRowAtIndexPath
la source
Après avoir vu la suggestion de Paulw11 d'utiliser un rappel de délégué, je voulais développer légèrement dessus / proposer une autre suggestion similaire. Si vous ne souhaitez pas utiliser le modèle de délégué, vous pouvez utiliser les fermetures dans Swift comme suit:
Votre classe de cellule:
Votre
cellForRowAtIndexPath
méthode:la source
J'ai trouvé un moyen très simple d'utiliser pour gérer n'importe quelle cellule dans tableView et collectionView en utilisant une classe Model et cela fonctionne aussi parfaitement.
Il existe en effet une bien meilleure façon de gérer cela maintenant. Cela fonctionnera pour gérer la cellule et la valeur.
Voici ma sortie (capture d'écran) alors voyez ceci:
RNCheckedModel
, écrivez le code comme ci-dessous.la source
J'ai utilisé la méthode convertPoint pour obtenir le point de tableview et passer ce point à la méthode indexPathForRowAtPoint pour obtenir indexPath
la source
Essayez d'utiliser #selector pour appeler l'IBaction. Dans le cellforrowatindexpath
De cette façon, vous pouvez accéder au chemin d'index dans la méthode editButtonPressed
la source
Dans mon cas, j'ai plusieurs sections et l'index de la section et de la ligne est vital, donc dans un tel cas, je viens de créer une propriété sur UIButton dont j'ai défini la cellule indexPath comme suit:
Ensuite, définissez la propriété dans cellForRowAt comme ceci:
Ensuite, dans handleTapAction, vous pouvez obtenir l'indexPath comme ceci:
la source
Swift 4 et 5
Méthode 1 utilisant le délégué de protocole
Par exemple, vous avez un
UITableViewCell
avec nomMyCell
Créez maintenant un
protocol
Étape suivante, créez une extension de
UITableView
Dans votre
UIViewController
implémentation le protocoleMyCellDelegate
Méthode 2 utilisant des fermetures
Dans
UIViewController
la source
Dans Swift 3. Également utilisé des déclarations de garde, évitant une longue chaîne d'accolades.
la source
Parfois, le bouton peut être à l'intérieur d'une autre vue de UITableViewCell. Dans ce cas, superview.superview peut ne pas donner l'objet de cellule et donc indexPath sera nul.
Dans ce cas, nous devons continuer à trouver la vue supervisée jusqu'à ce que nous obtenions l'objet cellule.
Fonction pour obtenir un objet de cellule par superview
Maintenant, nous pouvons obtenir indexPath en appuyant sur le bouton comme ci-dessous
la source
la source