我有一个简单的情况。 UICollectionView和自定义UICollectionViewCellUICollectionView具有导航栏。自定义单元格具有图像。单击图像时,我想将第二个控制器推入导航堆栈。我向自定义视图中的图像添加了轻击手势。如何从单元格访问父控制器中的导航栏?还是应该将点击手势添加到UICollectionView而不是UICollectionViewCell单元中?

self.templateImage.userInteractionEnabled = YES;
self.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGestureRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSelect:)];
[self.templateImage addGestureRecognizer:tapGestureRecog];
[self addGestureRecognizer:tapGestureRecog];

templateImage是单元格内的图像。在initWithCoderUICollectionViewCell方法内部调用此代码。所以我想我的问题是如何从视图访问控制器。通常,这可以通过IBAction完成。 iOS的新手:)

最佳答案

如其他答案中所述,you can only attach a gesture recognizer to one view

您总是可以让UICollectionView将手势识别器添加到cellForItemAtIndexPath:的集合视图单元格中

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CustomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCustomCollectionViewCellIdentifier forIndexPath:indexPath];
    if (cell.contentView.gestureRecognizers.count == 0) {
        [cell.contentView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myViewWasTapped:)]];
    }

    return cell;
}

如果采用这种方法,则必须确保如果重复使用单元格,则不要连续向同一单元格添加手势识别器。您可以检查视图的gestureRecognizers属性,以查看单元格的contentView是否已具有手势识别器。

轻敲单元格后,您就可以访问通过传入方法view的gestureRecognizer的myViewWasTapped:(UIGestureRecognizer *)sender属性轻敲的视图。

另一种方法是使用委托,这是一种在iOS中传递信息的流行方法。如果您将UICollectionViewCell子类化,则可以为该单元的“委托”声明一个协议。基本上,这只是对象要成为单元委托时应实现的所有方法的列表。在UICollectionViewCell h文件中,可以通过以下方式声明协议。
@class CustomCardCollectionViewCell;

@protocol CustomCollectionViewCellDelegate <NSObject>
@required
- (void)customCollectionViewCellWasTapped:(CustomCollectionViewCell *)cell;
@end

然后,在单元的界面中,您将声明一个称为委托的属性(尽管您可以随意调用它)。委托的类型为id,它符合协议CustomCollectionViewCellDelegate或您决定调用的协议。
@interface CustomCollectionViewCell : UICollectionViewCell
    @property (weak, nonatomic) id<CustomCollectionViewCellDelegate> delegate;

    //Other interface declaration stuffs.
@end

重要的是,UICollectionView在创建单元格时必须将其委托属性设置为自身。您可以将其视为从CustomCollectionViewCell指向UICollectionView的向后指针(这就是将委托属性声明为弱)的原因。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CustomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCustomCollectionViewCellIdentifier forIndexPath:indexPath];
    cell.delegate = self;

    return cell;
}

委托的好处是,委托不必是任何特定类型的对象,除了符合您定义的协议的对象。因此,您不需要自定义单元即可知道任何其他类。万岁!

您还需要记住,当单元格的手势识别器检测到轻击时,让单元格在其委托上调用该方法。
[self.delegate customCollectionViewCellWasTapped:self];

关注问题

如果您需要检测出是否点击了单元格的特定子视图,则有几种解决该问题的方法。一种方法是将子视图公开为UICollectionViewCell的子类上的 public 属性(也许是只读的),并将UIGestureRecognizer直接附加到该子视图,以便仅在点击子视图时才会触发。假设子视图是一个指示收藏夹的星形按钮。然后可以通过以下方式完成此操作。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CustomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCustomCollectionViewCellIdentifier forIndexPath:indexPath];
    if (cell.contentView.gestureRecognizers.count == 0) {
        [cell.starView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(starWasTapped:)]];
    }

    return cell;
}

您也可以在您的委托协议中添加一个委托方法。就像是
- (void)customCollectionCell:(CustomCollectionViewCell *)cell starViewWasTapped:(UIView *)starView

如果使用此方法,则可以让CustomCollectionViewCell将其手势识别器直接附加到星形视图,或者将手势识别器附加到单元格的contentView并计算手势识别器的locationInView是否落在starView的框架内。

您应该避免将手势识别器添加到内容视图,并避免让UICollectionView计算单元格中触摸的位置以确定星形是否被轻拍。原因是,这将要求UICollectionView知道恒星在单元的contentView中的位置。每个视图都应负责其子视图的位置。

如果星形是UIButton,则可以通过在按钮上设置tag属性并让UICollectionView将其自身添加为按钮上的目标来完全放弃UIGestureRecognizer。然后,您可以通过检查与操作一起发送的按钮的tag属性,来知道在哪个单元格中轻拍了哪个按钮。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CustomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCustomCollectionViewCellIdentifier forIndexPath:indexPath];
    [cell.starButton addTarget:self action:@selector(starButtonWasTapped:) forControlEvents:UIControlEventTouchUpInside];
    cell.starButton.tag = indexPath.row;

    return cell;
}

- (void)starButtonWasTapped:(UIButton *)starButton {
    //Do something based off of the tag of the button.
}

关于ios - 如何通过轻击手势从 View 与 Controller 对话,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21793356/

10-14 21:25