216 votes

En détectant UIButton a été pressé dans un UITableView

J'ai un UITableView avec 5 UITableViewCells. Chaque cellule contient un UIButton qui est défini 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: en buttonPressedAction: méthode, comment puis-je savoir quel bouton a été pressé. J'ai considéré l'utilisation de balises, mais je ne suis pas sûr que c'est le meilleur itinéraire. J'aimerais être capable de quelque étiquette de l' 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. 
}

Quel est le niveau moyen de faire cela?

Edit:

J'ai un peu résolu en procédant comme suit. J'aimerais avoir un avis si c'est la façon habituelle de faire, ou est-il un meilleur moyen?

- (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 est que je ne peux pas définir la balise dans la création de la cellule depuis la cellule peut être retiré à la place. Il se sent très sale. Il doit y avoir une meilleure façon.

402voto

Vladimir Points 110327

Apple, avec son Accessoire de l'échantillon la méthode suivante est utilisée:

[button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

Alors en contact gestionnaire de contact coordonnées récupérées et chemin d'index est calculé à partir de coordonnées:

- (void)checkButtonTapped:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    if (indexPath != nil)
    {
     ...
    }
}

48voto

Cocoanut Points 576

J'ai trouvé la méthode d'utilisation de la superview de superview pour obtenir une référence à la cellule indexPath a parfaitement fonctionné. Grâce à iphonedevbook.com (macnsmith) pour l'astuce, lien texte

-(void)buttonPressed:(id)sender {
 UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
 NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...

}

43voto

Chris Schwerdt Points 463

Voici comment je le fais. Simple et concis:

- (void)buttonTappedAction:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero
                                           toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    ...

6voto

Alpinista Points 1799

Trouvé une belle solution à ce problème ailleurs, pas de déconner avec des étiquettes sur le bouton:

- (void)buttonPressedAction:(id)sender {

NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];

do stuff with the indexPath...
}

5voto

magno cardona Points 61

Comment au sujet de l'envoi de l'information comme NSIndexPath dans la UIButton à l'aide d'exécution de l'injection.

1) Vous devez d'exécution sur l'importation

2) ajouter constante statique

3) ajouter l' NSIndexPath de votre bouton de l'exécution à l'aide de:

(void)setMetaData:(id)cible withObject:(id)newObj

4) appuyez sur le bouton obtenir des métadonnées à l'aide de:

(id)métadonnées:(id)de la cible

Profitez de

    #import <objc/runtime.h>
    static char const * const kMetaDic = "kMetaDic";


    #pragma mark - Getters / Setters

- (id)metaData:(id)target {
    return objc_getAssociatedObject(target, kMetaDic);
}

- (void)setMetaData:(id)target withObject:(id)newObj {
    objc_setAssociatedObject(target, kMetaDic, newObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}



    #On the cell constructor
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    ....
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    ....
    [btnSocial addTarget:self
                                   action:@selector(openComments:)
                         forControlEvents:UIControlEventTouchUpInside];

    #add the indexpath here or another object
    [self setMetaData:btnSocial withObject:indexPath];

    ....
    }



    #The action after button been press:

    - (IBAction)openComments:(UIButton*)sender{

        NSIndexPath *indexPath = [self metaData:sender];
        NSLog(@"indexPath: %d", indexPath.row);

        //Reuse your indexpath Now
    }

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