web-dev-qa-db-fra.com

comment accéder à UICollectionViewCell au chemin indexPath de la cellule dans UICollectionView

je veux animer le UICollectionViewCell quand l'action est appelée.
J'ai fait UICollectionViewCell dans Interface Builder, le UICollectionView également . Maintenant, je veux obtenir le indexPath correct à ma méthode actionBtnAddToCard.

c’est ce que j’essaie maintenant (méthode dans ProduktViewCell.m): 

- (IBAction)actionAddToCart:(id)sender {
    XLog(@"");

    // see this line
    NSIndexPath *indexPath = ??** how can i access the correct indexPath**??;
    SortimentViewController *svc = [[SortimentViewController alloc] initWithNibName:@"SortimentViewController_iPad" bundle:[NSBundle mainBundle]];
    [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];

    [svc collectionView:svc.collectionViewProdukte didSelectItemAtIndexPath:indexPath];
} 

SortimentViewController est le viewController qui hérite de UICollectionView.
comment accéder au bon indexPath?  

UPDATE 1: publication modifiée pour une meilleure compréhension.

20
brush51

si vous connaissez la hiérarchie des vues, c'est facile.

UIButton *button = (UiButton *) sender;

si le bouton est comme ceci -> UITableViewCell -> bouton

alors vous pouvez obtenir une cellule comme celle-ci 

UITableViewCell *cell = (UITableViewCell *)[button superview];

si le bouton est comme ceci -> UITableViewCell -> affichage du contenu -> bouton

UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];

et enfin le chemin de l'index peut être extrait comme ça 

NSIndexPath *indexPath = [self.table_View indexPathForCell:cell];
17
Shubhank
- (IBAction)actionAddToCart:(id)sender {
   NSIndexPath *indexPath;
   indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]]; 
   ...
}
25
carmen_munich

Ne comptez pas sur la vue ... Essayez ceci.

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:buttonPosition];

NSLog(@"%ld", (long)indexPath.row);
7
Ego Slayer

L'utilisation d'un code tel que [[button superview] superview] est fragile et non pérenne; en effet, il n'est même pas garanti de fonctionner sur toutes les versions d'iOS, à moins que vous ne le testiez explicitement. J'utilise toujours une méthode d'assistance itérative à cette fin: -

- (UIView *)superviewWithClassName:(NSString *)className fromView:(UIView *)view
{
    while (view)
    {
        if ([NSStringFromClass([view class]) isEqualToString:className])
        {
            return view;
        }
        view = view.superview;
    }
    return nil;
}

Ensuite, je l'appelle depuis le gestionnaire de boutons, comme suit: -

- (IBAction)buttonClicked:(id)sender
{
    UIButton *button = (UIButton *)sender;
    UICollectionViewCell *cell = (UICollectionViewCell *)
                                [self superviewWithClassName:@"UICollectionViewCell"
                                fromView:button];
    if (cell)
    {
        NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
        // do whatever action you need with the indexPath...
    }
}

UPDATE: Version rapide de superviewWithClassName. Faites-en une méthode de classe car elle ne fait jamais référence à self.

static func superviewWithClassName(className:String, fromView view:UIView?) -> UIView? {
    guard let classType = NSClassFromString(className) else {
        return nil
    }
    var v:UIView? = view
    while (v != nil) {
        if v!.isKindOfClass(classType) {
            return v
        }
        v = v!.superview
    }
    return nil
}

et du code pour l'appeler, à partir de prepareForSegue ou d'un gestionnaire de boutons: -

guard let cell = UIView.superviewWithClassName("UICollectionViewCell", fromView: sender as? UIView) as? UITableViewCell else {return}
6
Echelon

Swift solution: Une extension UICollectionView comme celle-ci peut être utile à cet effet.

extension UICollectionView {
    func indexPathForView(view: AnyObject) -> NSIndexPath? {
        let originInCollectioView = self.convertPoint(CGPointZero, fromView: (view as! UIView))
        return self.indexPathForItemAtPoint(originInCollectioView)
    }
}

L'utilisation devient facile partout.

let indexPath = collectionView.indexPathForView(button)
5
Ishan Handa

Si vous souhaitez animer une cellule spécifique, vous devez obtenir une référence à cette cellule. Appeler simplement 

[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];

ne fait rien. Vous devez conserver la cellule renvoyée par la méthode, comme ceci:

UICollectionViewCell *cell = [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];

Après cela, allez-y et animez:

[UIView animateWithDuration:0.2f animations:^{
    cell.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
}];
3
Tim

Vous pouvez le faire comme ceci, indexPathsForVisibleItems retournera un tableau de NSIndexPaths pour les éléments actuellement visibles et le premier objet retournera le premier (si vous avez une cellule par vue). 

NSIndexPath *indexPath = [[svc.collectionViewProdukte indexPathsForVisibleItems] firstObject]
3
Markus

Swift 3 Solution: basée sur la réponse d'Ishan Handa

extension UICollectionView {
func indexPathForView(view: AnyObject) -> IndexPath? {
    let originInCollectioView = self.convert(CGPoint.zero, from: (view as! UIView))
    return self.indexPathForItem(at: originInCollectioView) as IndexPath?
  }
}

Usage: 

func deleteCell(sender:UIButton){
    var indexPath:IndexPath? = nil
    indexPath = self.collectionView.indexPathForView(view: sender)        
    print("index path : \(indexPath)")
}
2
bpolat
//Note: this is for a storyboard implementation

// here is code for finding the row and section of a textfield being edited in a uicollectionview
UIView *contentView = (UIView *)[textField superview];
UICollectionViewCell *cell = (UICollectionViewCell *)[contentView superview];
cell = (UICollectionViewCell *)[contentView superview];

// determine indexpath for a specific cell in a uicollectionview
NSIndexPath *editPath = [myCollectionView indexPathForCell:cell];
int rowIndex = editPath.row;
int secIndex = editPath.section;
1
RFAustin

Même si beaucoup de réponses que j'ai trouvées ici, ce sera le plus court et utile quelle que soit la hiérarchie des vues. 

- (void) actionAddToCart:(id)sender
{
    id view = [sender superview];

    while (view && [view isKindOfClass:[UICollectionViewCell class]] == NO) 
    {
        view = [view superview];
    }
    NSIndexPath *thisIndexPath = [self.collectionView indexPathForCell:view];

    NSLog(@"%d actionAddToCart pressed",thisIndexPath.row);
}
1
Asta ni enohpi

Xcode10. Swift version 4.2.

extension UICollectionView {

  func indexPathForView(view: AnyObject) -> IndexPath? {
      guard let view = view as? UIView else { return nil }
      let senderIndexPath = self.convert(CGPoint.zero, from: view)
      return self.indexPathForItem(at: senderIndexPath)
  }

}

Usage:

// yourView can be button for example
let indexPath = collectionView.indexPathForView(view: yourView) 
0
Alex Kolovatov

Vous avez presque certainement une sous-classe UICollectionViewCell. Ajoutez simplement une propriété et définissez indexPath dans cellForItemAtIndexPath.

0
arsenius