ios 如何从 UICollectionViewCell 访问 UICollectionView 中 Cell 的 indexPath

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13875428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:33:41  来源:igfitidea点击:

how to access from UICollectionViewCell the indexPath of the Cell in UICollectionView

iosibactionuicollectionviewnsindexpathuicollectionviewcell

提问by brush51

i want to animate the UICollectionViewCellwhen action is called.
i have done UICollectionViewCellin Interface Builder, the UICollectionViewalso. Now i want to get the correct indexPathat my actionBtnAddToCardmethod.

我想UICollectionViewCell为调用动作的时间设置动画。
我已经完成UICollectionViewCellInterface BuilderUICollectionView也。现在我想indexPath在我的actionBtnAddToCard方法中得到正确的结果。

thats the way i try it now (method in ProduktViewCell.m):

这就是我现在尝试的方式(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 is the viewController which inherits the UICollectionView.
how to acces the correct indexPath?

SortimentViewController 是继承 UICollectionView 的 viewController。
如何访问正确的indexPath?

UPDATE 1: edited post for better understanding.

更新 1:编辑帖子以便更好地理解。

采纳答案by Shubhank

if you know the view hierarchy it is easy.

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

UIButton *button = (UiButton *) sender;

if the button is like this - > UITableViewCell - > button

如果按钮是这样的 -> UITableViewCell -> 按钮

then you can get cell like this

然后你可以得到这样的细胞

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

if the button is like this - > UITableViewCell - > content view -> button

如果按钮是这样的 -> UITableViewCell -> 内容视图 -> 按钮

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

and finally index path can be extracted like this

最后可以像这样提取索引路径

NSIndexPath *indexPath = [self.table_View indexPathForCell:cell];

回答by carmen_munich

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

回答by Ego Slayer

Do Not Depend on view. Try this.

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

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

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

回答by Echelon

Using code like [[button superview] superview]is fragile and not future-proof; indeed, it's not even guaranteed to work on all iOS versions unless you explicitly test it. I always use an iterative helper method for this purpose:-

使用像这样的代码[[button superview] superview]是脆弱的,而且不是面向未来的;事实上,除非您明确测试它,否则它甚至不能保证适用于所有 iOS 版本。为此,我总是使用迭代辅助方法:-

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

Then I call it from the button handler like so:-

然后我从按钮处理程序中调用它,如下所示:-

- (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: Swift version of superviewWithClassName. Made it a class method since it never references self.

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

and some code to call it, either from prepareForSegueor a button handler:-

和一些调用它的代码,无论是从prepareForSegue还是按钮处理程序:-

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

回答by Ishan Handa

Swiftsolution: A UICollectionView extension like this one can be useful for this.

Swift解决方案:像这样的 UICollectionView 扩展对此很有用。

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

Usage becomes easy everywhere.

使用变得容易无处不在。

let indexPath = collectionView.indexPathForView(button)

回答by Markus

You can do it like this, indexPathsForVisibleItems will return array of NSIndexPaths for items currently visible on view and first object returns the first one (if you have one cell per view).

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

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

回答by Tim

If you want to animate a specific cell, you need to get a reference to that cell. Simply calling

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

[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];

does nothing. You need to keep the cell that the method returns, like this:

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

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

After that, go ahead and animate:

之后,继续制作动画:

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

回答by bpolat

Swift 3 Solution : Based on Ishan Handa's Answer

Swift 3 解决方案:基于 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)")
}

回答by Asta ni enohpi

Even though many answer i found here .this will be shortest and useful irrespective of the view hierarchy

即使我在这里找到了很多答案。无论视图层次结构如何,这都是最短且有用的

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

回答by RFAustin

//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;