如何从UICollectionViewCell访问UICollectionView中Cell的indexPath

我想animationUICollectionViewCell行动时被调用。
我在Interface Builder UICollectionView也做了UICollectionView 。 现在我想在我的actionBtnAddToCard方法得到正确的indexPath

这就是我现在尝试的方式(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是inheritanceUICollectionView的viewController。
如何访问正确的indexPath?

更新1:编辑后更好的理解。

如果您知道视图层次结构,那很容易。

 UIButton *button = (UiButton *) sender; 

如果button是这样的– > UITableViewCell – >button

那么你可以得到这样的细胞

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

如果button是这样的– > UITableViewCell – >内容视图 – >button

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

最后可以像这样提取索引path

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

使用像[[button superview] superview]这样的代码是脆弱的,而不是面向未来的; 实际上,除非明确地testing,否则甚至不能保证可以在所有的iOS版本上运行。 我总是使用迭代辅助方法来达到这个目的:

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

然后我从button处理程序中调用它:

 - (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... } } 

更新: superviewWithClassName Swift版本。 使它成为一个类方法,因为它从不引用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 } 

和一些代码来调用它,无论是从prepareForSegue或button处理程序: –

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

不要依赖于视图。 尝试这个。

 CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.collectionView]; NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:buttonPosition]; NSLog(@"%ld", (long)indexPath.row); 

如果要为特定的单元格设置animation,则需要获取对该单元格的引用。 只需打电话

 [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath]; 

什么也没做。 您需要保持方法返回的单元格,如下所示:

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

之后,继续animation:

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

你可以这样做,indexPathsForVisibleItems将返回当前在视图中可见的项目的NSIndexPaths数组,并且第一个对象返回第一个(如果每个视图有一个单元格)。

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

Swift解决scheme:像这样的UICollectionView扩展可能对此有用。

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

用处变得容易到处。

 let indexPath = collectionView.indexPathForView(button) 

Swift 3解决scheme:基于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? } } 

用法:

 func deleteCell(sender:UIButton){ var indexPath:IndexPath? = nil indexPath = self.collectionView.indexPathForView(view: sender) print("index path : \(indexPath)") } 
 //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; 

即使我在这里find许多答案,这将是最短和有用的,不pipe视图的层次结构

 - (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); } 

你几乎可以肯定有一个UICollectionViewCell子类。 只需添加一个属性,并在cellForItemAtIndexPath中设置indexPath。