ios - superview 的手势是否应该在 iOS 7 中取消 subview 的手势?

标签 ios ios7 uigesturerecognizer touch-event

多年来,我一直假设如果父 View 及其 subview 都具有手势识别器,则 subview 将首先接收触摸并取消父 View 的手势。在 iOS 7 之前,这个假设从未让我失望,允许我向 subview 添加手势,确信父 View 的手势不会干扰。但在 iOS 7 中,父 View 会先随机接收触摸并取消 subview 的手势。这种情况很少发生,这使得问题很难被发现。

我第一次遇到这个问题是因为使用 UITapGestureRecognizer 无法点击按钮......再次,非常罕见。通常这些按钮会起作用,直到它们不起作用。让你有点怀疑你的理智。所以我推出了自己的 TapGestureRecognizer 并发现 superview tap 有时会取消其 subview 的 tap。在以前的任何 iOS 版本中都从未这样做过,但我想知道是否根本就没有 promise 过这种行为。

我认为 subview 的手势应该取消它的父 View 的手势(除非委托(delegate)人另有指定)。这是错误的还是错误?

请注意:我不是在问如何处理这种情况。我在问是否有人知道我的假设是否不正确。我已经在重新排列 View 、动态添加/删除手势并创建相当复杂的 gestureRecognizer:shouldReceiveTouch: 实现来补救这种情况。这不好玩,但我可以解决这个问题。

最佳答案

经过大量搜索后,我在 Apple 的留言板上发现了与遇到此问题的其他用户的讨论:Issues with UITapGestureRecognizer (需要开发者帐户)。我继续提交错误报告:15331126 (有人知道如何链接到错误报告吗?)。与此同时,我实现了这个解决方法。到目前为止它似乎工作正常,但由于该错误非常罕见,我可能只是还没有触发它。我将它发布给我的测试版用户,如果我没有收到他们的投诉(他们一直在提示),我会假设这解决了问题。

更新: 此解决方案已解决问题。经过数十位用户数周的使用,我没有遇到任何手势问题。

我的大多数手势都是习惯的。我将它们更改为自己的代表并实现:

- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    if (gestureRecognizer == self){
        if ([otherGestureRecognizer isMemberOfClass:self.class]){
            if ([self isGestureRecognizerInSuperviewHierarchy:otherGestureRecognizer]){
                return YES;
            } else if ([self isGestureRecognizerInSiblings:otherGestureRecognizer]){
                return YES;
            }
        }
    }
    return NO;
}

请注意,我的自定义 gestureRecognizers 现在实现了 UIGestureRecognizerDelegate 协议(protocol)(公开的,原因您将在下面看到)。我还向 UIGestureRecognizer 添加了几个类别(在上面的代码中使用):

- (BOOL) isGestureRecognizerInSiblings:(UIGestureRecognizer *)recognizer{
    UIView *superview = self.view.superview;
    NSUInteger index = [superview.subviews indexOfObject:self.view];
    if (index != NSNotFound){
    for (int i = 0; i < index; i++){
            UIView *sibling = superview.subviews[i];
            for (UIGestureRecognizer *viewRecognizer in sibling.gestureRecognizers){
                if (recognizer == viewRecognizer){
                    return YES;
                }
            }
        }
    }
    return NO;
}
- (BOOL) isGestureRecognizerInSuperviewHierarchy:(UIGestureRecognizer *)recognizer{
    if (!recognizer) return NO;
    if (!self.view) return NO;
    //Check siblings
    UIView *superview = self.view;
    while (YES) {
        superview = superview.superview;
        if (!superview) return NO;
        for (UIGestureRecognizer *viewRecognizer in superview.gestureRecognizers){
            if (recognizer == viewRecognizer){
                return YES;
            }
        }
    }
}

我不完全确定我是否需要检查 sibling ,因为我只看到 super View 手势出现问题。但是,我不想冒这个险。请注意,我只检查当前 View “下方”的 sibling ,因为我不想取消当前 View “上方”的 View 手势。

我必须为那些将自己设置为自定义识别器委托(delegate)的类添加实现,但它们几乎只是回调到 gestureRecognizer:

- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    if ([gestureRecognizer respondsToSelector:@selector(gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:)]){
        return [(id <UIGestureRecognizerDelegate>)gestureRecognizer gestureRecognizer:gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:otherGestureRecognizer];
    }
    return NO;
}

希望这对遇到问题的其他人有所帮助。

关于ios - superview 的手势是否应该在 iOS 7 中取消 subview 的手势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19095165/

相关文章:

ios - 模糊包含键盘及其下方内容的 UIView (iOS 7)

ios - 如果仅在 iOS 7 上设置动画,pushViewController 会导致黑屏

iOS:添加到 UIAlertView 的 GestureRecognizer 不调用其操作

ios - MFMessageComposeViewController 和 MFMailComposeViewController 未在 iPhone 5S 上显示

ios - 在长按手势时在 UIButton 中显示图像

ios - 滑动UITableViewCells如何实现?

android - 在 iOS 中管理核心对象

iphone - 显示的 NSLog 数组计数代码有什么作用?

ios - 如何使用属性编写 block 定义?

ios - 有没有办法在 SFSafariViewController 中传递 headerField 参数?