J'ai un UITableView
avec 5 UITableViewCells
. Chaque cellule contient un UIButton
qui est configuré comme suit:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelelase];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
[button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:1];
[cell.contentView addSubview:button];
[button release];
}
UIButton *button = (UIButton *)[cell viewWithTag:1];
[button setTitle:@"Edit" forState:UIControlStateNormal];
return cell;
}
Ma question est la suivante: dans la buttonPressedAction:
méthode, comment savoir quel bouton a été enfoncé. J'ai envisagé d'utiliser des balises, mais je ne suis pas sûr que ce soit le meilleur itinéraire. J'aimerais pouvoir en quelque sorte marquer le indexPath
sur le contrôle.
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
// how do I know which button sent this message?
// processing button press for this row requires an indexPath.
}
Quelle est la manière standard de procéder?
Éditer:
Je l'ai un peu résolu en faisant ce qui suit. Je voudrais quand même avoir une opinion sur le fait que ce soit la façon standard de le faire ou y a-t-il une meilleure façon?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelelase];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
[button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
[button release];
}
UIButton *button = (UIButton *)[cell.contentView.subviews objectAtIndex:0];
[button setTag:indexPath.row];
[button setTitle:@"Edit" forState:UIControlStateNormal];
return cell;
}
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
int row = button.tag;
}
Ce qui est important à noter, c'est que je ne peux pas définir la balise dans la création de la cellule car la cellule peut être retirée de la file d'attente à la place. C'est très sale. Il doit y avoir un meilleur moyen.
Réponses:
Dans l' exemple d' accessoire d'Apple, la méthode suivante est utilisée:
Ensuite, dans le gestionnaire tactile, les coordonnées tactiles sont récupérées et le chemin d'index est calculé à partir de ces coordonnées:
la source
J'ai trouvé que la méthode d'utilisation de la vue d'ensemble de la vue d'ensemble pour obtenir une référence à l'indexPath de la cellule fonctionnait parfaitement. Merci à iphonedevbook.com (macnsmith) pour le texte du lien de conseil
la source
Voici comment je le fais. Simple et concis:
la source
CGPointZero
place deCGPointMake(0, 0)
;-)A trouvé une bonne solution à ce problème ailleurs, sans déconner avec les balises sur le bouton:
la source
buttonPressedAction:
maisbuttonPressedAction:forEvent:
.Que diriez-vous d'envoyer les informations comme
NSIndexPath
dans leUIButton
injection d'exécution aide.1) Vous avez besoin de runtime à l'importation
2) ajouter une constante statique
3) ajouter
NSIndexPath
à votre bouton sur l'exécution en utilisant:(void) setMetaData: (id) cible withObject: (id) newObj
4) appuyez sur le bouton pour obtenir les métadonnées en utilisant:
(id) metaData: (id) cible
Prendre plaisir
la source
Pour faire (@Vladimir) la réponse est Swift:
Bien que la vérification
indexPath != nil
me donne le doigt ... "NSIndexPath n'est pas un sous-type de NSString"la source
Avec Swift 4.2 et iOS 12, vous pouvez choisir l'un des 5 exemples complets suivants afin de résoudre votre problème.
#1. Utilisation de
UIView
'convert(_:to:)
etUITableView
'indexPathForRow(at:)
# 2. Utilisation de
UIView
'convert(_:to:)
etUITableView
'indexPathForRow(at:)
(alternative)Ceci est une alternative à l'exemple précédent où nous passons
nil
autarget
paramètre dansaddTarget(_:action:for:)
. De cette façon, si le premier répondant n'implémente pas l'action, elle sera envoyée au prochain répondant de la chaîne de répondeurs jusqu'à ce qu'une implémentation correcte soit trouvée.# 3. Utilisation
UITableView
deindexPath(for:)
et modèle de déléguéDans cet exemple, nous définissons le contrôleur de vue comme délégué de la cellule. Lorsque le bouton de la cellule est tapé, il déclenche un appel à la méthode appropriée du délégué.
# 4. En utilisant
UITableView
« sindexPath(for:)
et une fermeture pour la délégationCeci est une alternative à l'exemple précédent où nous utilisons une fermeture au lieu d'une déclaration de délégué de protocole pour gérer le tap tap.
# 5. Utilisation de
UITableViewCell
'accessoryType
etUITableViewDelegate
'tableView(_:accessoryButtonTappedForRowWith:)
Si le bouton est un
UITableViewCell
« contrôle accessoire standard s, tout robinet sur elle déclenchera un appel àUITableViewDelegate
» stableView(_:accessoryButtonTappedForRowWith:)
, vous permettant d'obtenir le chemin d'index connexe.la source
la source
J'utiliserais la propriété de balise comme vous l'avez dit, en définissant la balise comme suit:
puis obtenir la balise à l'intérieur du boutonPressedAction comme ceci:
Ou
la source
tag
est un entier. semble un peu maladroit d'encoder / décoder les chemins d'index dans les balises de vue.Bien que j'aime la façon de tag ... si vous ne voulez pas utiliser de tags pour une raison quelconque, vous pouvez créer un membre
NSArray
de boutons prédéfinis:puis créez ces boutons avant de rendre la tableView et poussez-les dans le tableau.
Ensuite, à l'intérieur de la
tableView:cellForRowAtIndexPath:
fonction, vous pouvez faire:Ensuite, dans la
buttonPressedAction:
fonction, vous pouvez fairela source
POUR GÉRER LES SECTIONS - J'ai stocké le NSIndexPath dans une UITableViewCell personnalisée
IN CLKIndexPricesHEADERTableViewCell.xib
IN IB Ajouter UIButton à XIB - NE PAS ajouter d'action!
Ajouter une sortie @property (conserver, non anatomique) IBOutlet UIButton * buttonIndexSectionClose;
NE PAS CTRL + DRAG une action dans IB (fait dans le code ci-dessous)
In viewForHeaderInSection (devrait également fonctionner pour cellForRow .... etc si votre table n'a qu'une seule section)
... utilisez la section pour obtenir des données pour votre cellulaire
...compléter le
L'UTILISATEUR appuie sur le bouton SUPPRIMER sur un en-tête de section et cela appelle
Dans cet exemple, j'ai ajouté un bouton Supprimer et je devrais donc afficher UIAlertView pour le confirmer
Je stocke la section et la clé dans le dictionnaire stockant des informations sur la section dans un ivar dans le VC
la source
la source
Cela fonctionne aussi pour moi, merci @Cocoanut
J'ai trouvé que la méthode d'utilisation de la vue d'ensemble de la vue d'ensemble pour obtenir une référence à l'indexPath de la cellule fonctionnait parfaitement. Merci à iphonedevbook.com (macnsmith) pour le texte du lien de conseil
la source
vous pouvez utiliser le modèle de balise:
la source
Suis-je en train de manquer quelque chose? Ne pouvez-vous pas simplement utiliser l'expéditeur pour identifier le bouton. L'expéditeur vous donnera des informations comme celle-ci:
Ensuite, si vous souhaitez modifier les propriétés du bouton, dites l'image d'arrière-plan que vous venez de dire à l'expéditeur:
Si vous avez besoin de la balise, la méthode ACBurk est très bien.
la source
Assez simple en fait:
Fonctionne bien pour moi: P
si vous souhaitez ajuster votre configuration d'action cible, vous pouvez inclure le paramètre d'événement dans la méthode, puis utiliser les touches de cet événement pour résoudre les coordonnées de la touche. Les coordonnées doivent encore être résolues dans les limites de la vue tactile, mais cela peut sembler plus facile pour certaines personnes.
la source
créer un tableau nsmutable et mettre tous les boutons dans ce tableau usint [array addObject: yourButton];
dans la méthode de pression des boutons
-
la source
Une légère variation sur la réponse Cocoanuts (qui m'a aidé à résoudre ce problème) lorsque le bouton était dans le pied de page d'un tableau (ce qui vous empêche de trouver la `` cellule cliquée '':
la source
J'utilise toujours des tags.
Vous devez sous-classer le
UITableviewCell
et gérer la pression sur le bouton à partir de là.la source
C'est simple; faire une cellule personnalisée et prendre une sortie de bouton
changer l'identifiant de la méthode ci-dessus en
(UIButton *)
Vous pouvez obtenir la valeur de quel bouton est exploité en faisant sender.tag.
la source
Sous-classe le bouton pour stocker la valeur requise, peut-être créer un protocole (ControlWithData ou quelque chose). Définissez la valeur lorsque vous ajoutez le bouton à la cellule de vue tabulaire. Lors de votre retouche, vérifiez si l'expéditeur respecte le protocole et extrayez les données. Je stocke normalement une référence à l'objet réel qui est rendu dans la cellule de vue de table.
la source
MISE À JOUR SWIFT 2
Voici comment savoir quel bouton a été tapé + envoyer des données à un autre ViewController à partir de ce bouton
indexPath.row
car je suppose que c'est le point pour la plupart!Pour ceux qui utilisent une classe ViewController et ont ajouté un tableView, j'utilise un ViewController au lieu d'un TableViewController, j'ai donc ajouté manuellement le tableView afin d'y accéder.
Voici le code pour passer des données à un autre VC en appuyant sur ce bouton et en passant la cellule
indexPath.row
la source
Notez ici que j'utilise une cellule personnalisée, ce code fonctionne parfaitement pour moi
la source
La solution de Chris Schwerdt mais chez Swift a fonctionné pour moi:
la source
Ce problème se compose de deux parties:
1) Obtenir le chemin d'index
UITableViewCell
qui contient presséUIButton
Il y a quelques suggestions comme:
Mise à jour de
UIButton
la méthodetag
in encellForRowAtIndexPath:
utilisant larow
valeur du chemin d'index . Ce n'est pas une bonne solution car elle nécessite une misetag
à jour continue et ne fonctionne pas avec les vues de table avec plus d'une section.Ajouter une
NSIndexPath
propriété à une cellule personnalisée et la mettre à jour au lieu deUIButton
la méthodetag
incellForRowAtIndexPath:
. Cela résout le problème de plusieurs sections mais n'est toujours pas bon car il nécessite toujours une mise à jour.Garder une référence faible au parent
UITableView
dans la cellule personnalisée lors de sa création et utiliser laindexPathForCell:
méthode pour obtenir le chemin d'index. Semble un peu mieux, pas besoin de mettre à jour quoi que ce soit dans lacellForRowAtIndexPath:
méthode, mais nécessite toujours de définir une référence faible lorsque la cellule personnalisée est créée.Utilisation de la
superView
propriété de la cellule pour obtenir une référence au parentUITableView
. Pas besoin d'ajouter de propriétés à la cellule personnalisée et pas besoin de définir / mettre à jour quoi que ce soit lors de la création / plus tard. Mais la cellulesuperView
dépend des détails d'implémentation iOS. Il ne peut donc pas être utilisé directement.Mais cela peut être réalisé en utilisant une simple boucle, car nous sommes sûrs que la cellule en question doit être dans un UITableView:
Ainsi, ces suggestions peuvent être combinées en une méthode de cellule personnalisée simple et sûre pour obtenir le chemin d'index:
Désormais, cette méthode peut être utilisée pour détecter lequel
UIButton
est pressé.2) Informer les autres parties de l'événement de presse de bouton
Après avoir su en interne qui
UIButton
est pressé dans quelle cellule personnalisée avec un chemin d'index exact, ces informations doivent être envoyées à d'autres parties (probablement le contrôleur de vue qui gère leUITableView
). Ainsi, cet événement de clic de bouton peut être géré dans un niveau d'abstraction et de logique similaire à ladidSelectRowAtIndexPath:
méthode du délégué UITableView.Deux approches peuvent être utilisées pour cela:
a) Délégation: une cellule personnalisée peut avoir une
delegate
propriété et peut définir un protocole. Lorsque le bouton est enfoncé, il exécute simplement ses méthodes déléguées sur sadelegate
propriété. Mais cettedelegate
propriété doit être définie pour chaque cellule personnalisée lors de leur création. Comme alternative, la cellule personnalisée peut également choisir d'exécuter ses méthodes de délégué sur sa vue de table parentdelegate
.b) Centre de notifications: les cellules personnalisées peuvent définir un nom de notification personnalisé et publier cette notification avec le chemin d'index et les informations de vue de la table parent fournies dans l'
userInfo
objet. Pas besoin de définir quoi que ce soit pour chaque cellule, il suffit d'ajouter un observateur pour la notification de la cellule personnalisée.la source
J'utilise une solution de cette sous-classe
UIButton
et j'ai pensé que je devrais simplement la partager ici, les codes dans Swift:N'oubliez pas de mettre à jour son indexPath dans
cellForRow(at:)
Ainsi, lorsque vous répondez à l'événement du bouton, vous pouvez l'utiliser comme
la source