web-dev-qa-db-fra.com

accessoryButtonTappedForRowWith IndexPath: ne pas être appelé

Je crée un bouton de divulgation de détail qui se remplit à l'aide d'un tableau .... Cependant, la fonction accessoryButtonTappedForRowWithIndexPath: n'est pas appelée dans ma classe. Il s'agit d'un délégué TableviewDelegate et TableviewDatasource.

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"reaching accessoryButtonTappedForRowWithIndexPath:");
    [self performSegueWithIdentifier:@"modaltodetails" sender:[self.eventsTable cellForRowAtIndexPath:indexPath]];
}

Le NSLog n'imprime pas sur la console, ce qui m'amène à croire que la fonction n'est pas appelée ... C'est bien sûr quand je sélectionne sur une cellule. Une capture d'écran ci-dessous montre comment j'ai configuré ma cellule.

enter image description here

29
jimbob

Vous venez de cliquer sur la cellule pour la sélectionner ou avez-vous réellement cliqué sur l'indicateur de bouton accessoire sur la cellule? Cela ne ressort pas clairement de votre question.

accessoryButtonTappedForRowWithIndexPath est applicable lorsque vous cliquez sur l'icône du bouton dans la cellule et non lorsque vous sélectionnez la cellule.

7
Coder

Le doc dit que la méthode tableView:accessoryButtonTappedForRowWithIndexPath: n'est pas appelé lorsqu'une vue accessoire est définie pour la ligne à indexPath. La méthode n'est appelée que lorsque la propriété accessoryView est nil et lorsque l'on utilise et définit la propriété accessoryType pour afficher une vue d'accessoire intégrée.

Si je comprends bien, accessoryView et accessoryType s'excluent mutuellement. Lorsque vous utilisez accessoryType, le système appellera tableView:accessoryButtonTappedForRowWithIndexPath: comme prévu, mais vous devez gérer l'autre cas par vous-même.

La manière Apple fait cela est indiquée dans l'exemple de projet Accessory du SDK. Dans la méthode cellForRowAtIndexPath du délégué dataSource, ils définissent une cible/action à un bouton accessoire personnalisé. Puisqu'on ne peut pas passer le indexPath à l'action, ils appellent une méthode auxiliaire pour récupérer le indexPath correspondant et ils passent le résultat à la méthode déléguée:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    ...

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    ...

    // set the button's target to this table view controller so we can interpret touch events and map that to a NSIndexSet
    [button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
    ...
    cell.accessoryView = button;

    return cell;
}


- (void)checkButtonTapped:(id)sender event:(id)event{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
    if (indexPath != nil){
        [self tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath];
    }
}

Pour une raison quelconque, votre configuration semble tomber dans le boîtier accessoireView. Avez-vous essayé de définir le accessoryType avec du code au lieu d'utiliser le générateur d'interface?

59
Tom

Cela semble très pertinent ...

Indicateur de divulgation: Lorsque cet élément est présent, les utilisateurs savent qu'ils peuvent appuyer n'importe où dans la ligne pour voir le niveau suivant dans la hiérarchie ou les choix associés à l'élément de liste. Utilisez un indicateur de divulgation dans une ligne lorsque la sélection de la ligne entraîne l'affichage d'une autre liste. N'utilisez pas d'indicateur de divulgation pour révéler des informations détaillées sur l'élément de liste; utilisez plutôt un bouton de divulgation détaillée à cet effet.

bouton de divulgation détaillée: les utilisateurs tapent sur cet élément pour voir des informations détaillées sur l'élément de liste. (Notez que vous pouvez utiliser cet élément dans des vues autres que des vues de table, pour révéler des détails supplémentaires sur quelque chose; voir "Boutons de divulgation détaillée" pour plus d'informations.) Dans une vue de table, utilisez un bouton de divulgation détaillée dans une ligne pour afficher des détails sur l'élément de liste. Notez que le bouton de divulgation des détails, contrairement à l'indicateur de divulgation, peut effectuer une action distincte de la sélection de la ligne. Par exemple, dans les Favoris du téléphone, appuyer sur la ligne lance un appel vers le contact; appuyer sur le bouton de divulgation des détails dans la ligne révèle plus d'informations sur le contact.

38
mdebeus

Conversion de la première réponse en Swift 3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    ...
    let unseletcedImage = UIImage(named: "<imagename>")
    let seletcedImage = UIImage(named: "<imagename>")
    let button = UIButton(type: .custom)
    // match the button's size with the image size
    let frame = CGRect(x: CGFloat(0.0), y: CGFloat(0.0), width: CGFloat((unseletcedImage?.size.width)!), height: CGFloat((unseletcedImage?.size.height)!))
    button.frame = frame
    button.setBackgroundImage(unseletcedImage, for: .normal)
    button.setBackgroundImage(seletcedImage, for: .selected)
    cell?.accessoryView = button
    let action = #selector(checkButtonTapped(sender:event:))
    (cell?.accessoryView as? UIButton)?.addTarget(self, action: action, for: .touchUpInside)
    ....
    return cell!

}

@objc func checkButtonTapped(sender: UIButton?, event: UIEvent) {
    let touches = event.allTouches
    let touch = touches!.first
    guard let touchPosition = touch?.location(in: self.tableView) else {
        return
    }
    if let indexPath = tableView.indexPathForRow(at: touchPosition) {
        tableView(self.tableView, accessoryButtonTappedForRowWith: indexPath)
    }
}
10
Keith Coughtrey

Selon la documentation de UITableViewCellAccessoryType, il s'agit d'un comportement attendu:

typedef enum : NSInteger {    
UITableViewCellAccessoryNone,   
UITableViewCellAccessoryDisclosureIndicator,   
UITableViewCellAccessoryDetailDisclosureButton,   
UITableViewCellAccessoryCheckmark,   
UITableViewCellAccessoryDetailButton } UITableViewCellAccessoryType;

Constantes UITableViewCellAccessoryNone La cellule n'a pas de vue accessoire. Ceci est la valeur par défault.

UITableViewCellAccessoryDisclosureIndicator La cellule a un contrôle accessoire en forme de chevron. Ce contrôle indique que le fait d'appuyer sur la cellule déclenche une action Push. Le contrôle ne suit pas touche.

UITableViewCellAccessoryDetailDisclosureButton La cellule a un bouton info et une image chevron comme contenu. Ce contrôle indique que le fait d'appuyer sur la cellule permet à l'utilisateur de configurer le contenu de la cellule. Le contrôle pistes touche.

UITableViewCellAccessoryCheckmark La cellule a une coche sur son côté droit. Ce contrôle ne suit pas touche. Le délégué de la vue tableau peut gérer les coches dans une section de lignes (en limitant éventuellement la coche à une ligne de la section) dans sa méthode tableView: didSelectRowAtIndexPath:.

UITableViewCellAccessoryDetailButton La cellule a un bouton info sans chevron. Ce contrôle indique que le fait d'appuyer sur la cellule affiche des informations supplémentaires sur le contenu de la cellule. Le contrôle pistes touche.

9
Avt

a attiré sur place.

Si vous passez à "DetailDisclosure" dans Storyboard, la méthode se déclenchera. (xCode 4.6 DP3)

2
wm_j_ray

C'est une autre façon de gérer le bouton de divulgation à l'aide du storyboard. Vous devez cliquer sur la cellule de vue tabulaire et accéder à l'inspecteur de connexions. Il existe une section intitulée Séquences déclenchées, et vous pouvez faire glisser de la ligne de sélection vers l'UIViewController vers lequel vous souhaitez effectuer la transition. La séquence se produit automatiquement et vous pouvez capturer prepareForSegue pour capturer la notification lorsqu'elle le fait.
La fonction accessoryButtonTappedForRowWithIndexPath n'est jamais appelée pour le bouton de divulgation. Il est uniquement appelé pour le bouton de divulgation détaillée.

0
nishant