如何通过轻击手势从视图到控制器进行通话

时间:2014-02-15 04:20:46

标签: ios objective-c uicollectionview uicollectionviewcell

我的情况很简单。 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是单元格内的图像。此代码在initWithCoder的{​​{1}}方法内调用。所以我想我的问题是如何从视图中访问控制器。通常这将使用UICollectionViewCell来完成。新手到iOS:)

1 个答案:

答案 0 :(得分:1)

正如其他答案所述,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

然后在您的单元格界面中,您将声明一个名为delegate的属性(尽管您可以随意调用它)。委托类型为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的子类上,并将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,你可以完全放弃UIGestureRecognizer,方法是在按钮上设置tag属性,让UICollectionView将它自己添加为按钮上的目标。然后,您可以通过检查随操作一起发送的按钮的标记属性来判断在哪个按钮中点击了哪个按钮。

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