我的手势识别器附加到错误的视图

时间:2014-06-08 19:20:46

标签: ios objective-c uigesturerecognizer

我有一个UICollectionView,它包含可以在屏幕上拖放的元素。我使用UILongPressGestureRecognizer来处理拖动。我将此识别器附加到我的collectionView:cellForItemAtIndexPath:方法中的集合视图单元格中。但是,识别器的视图属性偶尔会返回UIView而不是UICollectionViewCell。我需要一些仅在UICollectionViewCell上的方法/属性,而当我的应用程序返回UIView时,我的应用程序崩溃了。

为什么连接到单元格的识别器会返回一个简单的UIView?

附加识别器

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{
    EXSupplyCollectionViewCell *cell = (EXSupplyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
    UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:nil];
    longPressRecognizer.delegate = self;
    [cell addGestureRecognizer:longPressRecognizer];
    return cell;
}

处理手势

我使用带有switch语句的方法来分派长按的不同状态。

- (void)longGestureAction:(UILongPressGestureRecognizer *)gesture {
    UICollectionViewCell *cell = (UICollectionViewCell *)[gesture view];
    switch ([gesture state]) {
        case UIGestureRecognizerStateBegan:
            [self longGestureActionBeganOn:cell withGesture:gesture];
            break;
        //snip
        default:
            break;
    }
}

如果longGestureActionBeganOn:withGesture实际上是cell,则调用UICollectionViewCell时手势的其余部分会完美执行。如果它不是,那么它在尝试确定应该是单元格的索引路径时会中断。

第一次出现中断

- (void)longGestureActionBeganOn:(UICollectionViewCell *)cell withGesture:(UILongPressGestureRecognizer *)gesture
{
    NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell]; // unrecognized selector is sent to the cell here if it is a UIView
    [self.collectionView setScrollEnabled:NO];
    if (indexPath != nil) {
        // snip
    }
}

我还使用特定于UICollectionViewCell的其他属性来处理手势的其他状态。是否有某种方法可以保证识别器始终会将我分配给它的视图返回给我?

2 个答案:

答案 0 :(得分:5)

像UICollectionView和UITableView这样的视图将重用它们的单元格。如果您在collectionView:cellForItemAtIndexPath:中盲目添加gestureRecognizer,则每次重新加载单元格时都会添加一个新的。如果你滚动一下,你会在每个单元格上找到几十个gestureRecognizer。

理论上,除了多次调用gestureRecognizer的动作之外,这不会引起任何问题。但Apple在细胞重用方面使用了大量的性能优化,因此可能会出现某些问题。

解决问题的首选方法是改为add the gestureRecognizer to the collectionView

另一种方法是检查单元格上是否已有gestureRecognizer,如果没有则只添加新的。或者您使用找到的解决方案并删除单元格prepareForReuse中的gestureRecognizer。 当您使用后一种方法时,您应该检查是否删除(或测试)正确的方法。您不想删除系统为您添加的gestureRecognizers。 (我不确定iOS目前是否使用此功能,但为了让您的应用能够证明未来,您可能希望坚持这种最佳做法。)

答案 1 :(得分:0)

我有一个与Long-Touch有关的类似问题。 我最终要做的是重写UICollectionViewCell.PrepareForReuse并取消附加到我的视图的UIGestureRecognizers。因此,每次我的牢房被回收时,长按事件都将被取消。

See this answer