手势识别器在 iOS 4.3 中停止工作

Posted

技术标签:

【中文标题】手势识别器在 iOS 4.3 中停止工作【英文标题】:Gesture recognizer stopped working in iOS 4.3 【发布时间】:2011-03-14 04:02:29 【问题描述】:

我的手势识别代码在 ios 4.2 中运行良好,但在 iOS 4.3 中无法运行。我在 iOS 4.2 到 4.3 的手势识别器中找不到任何记录在案的更改,但我已经在 iPad 和模拟器中确认我的代码不再工作。

这就是我正在做的:

在我的视图控制器的 ViewDidLoad 方法中,我输入了:

UISwipeGestureRecognizer *swipeUpGesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreenLeft:)] autorelease];
swipeUpGesture.numberOfTouchesRequired = 2;
swipeUpGesture.direction = (UISwipeGestureRecognizerDirectionLeft);
[scrollView addGestureRecognizer:swipeUpGesture];

在 iOS 4.2 中,这可以按预期工作,但在 iOS 4.3 中,即使我用两根手指滑动,也不会调用 swipedScreenLeft。一切都编译并运行,但没有错误或警告。

有什么可能会阻止此手势识别器在 iOS 4.3 中工作,即使它在 iOS 4.2 中运行良好?

我还注意到,在 iOS 4.2 下,如果我用两根手指触摸屏幕但没有做出正确的手势,什么都不会发生,但在 iOS 4.3 中,如果我用两根手指触摸屏幕,就好像我只是用一根手指触摸。好像 iOS 4.3 无法识别我的应用程序中的多点触控事件。

另一个注意事项:我的 tapGestureRecognizer 在 iOS 4.3 中可以正常工作,只是 swipeGestureRecognizer 不能。

【问题讨论】:

同样的问题,在 iOS 4.3 中停止工作,之前很好。 我很高兴找到和我有同样问题的人。如果你想通了,请告诉我,我也会这样做。您的代码是否也在滚动视图上使用手势识别器? 我的手势识别器位于应用程序的主窗口中,因此可以在整个应用程序中使用。 【参考方案1】:

问题仅在于 UIScrollView,我也对此大发雷霆:http://i.stack.imgur.com/dqx3d.png

[更新 1] 这里的解决方案:

情况:一个 UIViewController 的视图有一个 UIScrollView 作为子视图(滚动视图分页被禁用)。

我用来将手势附加到 UIView 的代码:

UISwipeGestureRecognizer *swipeLeftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreenLeft:)];
[swipeLeftRecognizer setNumberOfTouchesRequired:2.0f];
swipeLeftRecognizer.delegate = self;
[swipeLeftRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];

[self.view addGestureRecognizer:swipeLeftRecognizer];

[swipeLeftRecognizer release];

要启用 iOS 4.3,我只需将 UIViewController 添加为 UIGestureRecognizerDelegate

然后,我使用以下委托方法拦截并允许同时识别滚动视图的 panGesture 和视图的滑动。代码如下:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

    if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) 
        return YES;
    

    return NO;


[更新 2]

要禁用用两根手指平移 UIScrollView,我认为您必须创建滚动视图,这是 UISCrollView 类的自定义子类并更改 panGesture 检测器的某些行为,但我没有尝试这样做。 相反,我选择了一个更懒的解决方案,基本上我根据 UISwipeGestureRecognizer 的当前状态启用/禁用 scrollView 滚动功能。 此外,为了防止在另一个方向上的双重触摸移动,我为此添加了另一个识别器。

您必须为滑动检测器创建两个属性。

@property (nonatomic,assign) UISwipeGestureRecognizer *swipeRightRecognizer;
@property (nonatomic,assign) UISwipeGestureRecognizer *swipeLeftRecognizer;

然后我这样编码:

[self setSwipeRightRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:nil action:nil]];
[swipeRightRecognizer setNumberOfTouchesRequired:2.0f];
swipeRightRecognizer.delegate = self;
[swipeRightRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[self addObserver:self forKeyPath:@"swipeRightRecognizer.state" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL];
[self.view addGestureRecognizer:swipeRightRecognizer];
[swipeRightRecognizer release];

[self setSwipeLeftRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreenLeft:)]];
[swipeLeftRecognizer setNumberOfTouchesRequired:2.0f];
swipeLeftRecognizer.delegate = self;
[swipeLeftRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[self addObserver:self forKeyPath:@"swipeLeftRecognizer.state" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL];
[self.view addGestureRecognizer:swipeLeftRecognizer];
[swipeLeftRecognizer release];

然后添加这个方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 

    if (self.swipeRightRecognizer.state == UIGestureRecognizerStateFailed) 
        self.scrollView.scrollEnabled = YES;
        return;
    

    if ([self.swipeRightRecognizer numberOfTouches] != 2.0f) 
        self.scrollView.scrollEnabled = YES;   
    
    else
        self.scrollView.scrollEnabled = NO;   
    

并更新我在之前“[UPDATE]”中发布的现有方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

    if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) 
        if ([gestureRecognizer numberOfTouches] != 2.0f) 
            self.scrollView.scrollEnabled = YES;   
        
        else
            self.scrollView.scrollEnabled = NO;   
        

        return YES;
    
    return NO;

最后,移除 dealloc 中的观察者:

[self removeObserver:self forKeyPath:@"swipeRightRecognizer.state"];
[self removeObserver:self forKeyPath:@"swipeLeftRecognizer.state"];

我敢打赌,有一个更清洁的解决方案,但它确实有效.. .

希望对你有帮助;)

【讨论】:

好的,所以我将 UIGestureRecognizerDelegate 添加到我的主视图控制器的头文件中:@interface MainViewController : UIViewController 然后像你一样定义委托方法: - (BOOL)gestureRecognizer:(UIGestureRecognizer *) gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer ... 但委托方法似乎从未被调用。我什至在其中放了一个 NSLog,但我从未在控制台中看到它弹出,所以有些奇怪。知道什么可能会阻止委托被调用吗? 我想我只需要将代理添加到我的每个手势中(例如 [swipeDownGesture setDelegate:self]; 等等...)。虽然这似乎可行,但行为仍然与 4.2 不同。在 iOS 4.2 中,当我用两根手指触摸我的 scrollView 时(例如,当我开始一个手势时)它不会滚动(它只会用一根手指滚动)。现在它似乎在我用两根手指尝试手势时滚动。知道为什么这种行为会有所不同吗? 太棒了,我今晚会看看这个,看看情况如何! 我认为在 shouldRecognizeSimultaneouslyWithGestureRecognizer 中添加 if 语句足以让它再次表现得像 iOS 4.2 应用程序(因此一切都再次正常工作)。非常感谢!如果您有兴趣,我想用我的应用程序的促销代码奖励您。我不确定你是否可以在这里私信我,但如果不能通过我的网站联系我,我会给你一个免费下载的代码! 其实可能没有解决。如果尝试了无法识别的两指手势,我的 scrollView 现在似乎有时无法锁定。嗯,也许我需要实现复杂的解决方案。我仍然无法弄清楚为什么这在 4.3 中有所不同。 Apple 没有很好地记录它。【参考方案2】:

如果你使用 UIImageView 并且你想处理双击它,你应该启用用户交互。我浪费了很多时间来发现这一点。

【讨论】:

【参考方案3】:

也许我的代码可以帮助您解决问题。 我已经在装有 iOS 4.3 的 iPad 上测试了代码 而且效果很好

UISwipeGestureRecognizer *oSwipeLeft = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(mPreviousPage:) ] autorelease];
oSwipeLeft.numberOfTouchesRequired = 2;
oSwipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:oSwipeLeft];

UISwipeGestureRecognizer *oSwipeRight = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(mNextPage:) ] autorelease];
oSwipeRight.numberOfTouchesRequired = 2;
oSwipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:oSwipeRight];

UISwipeGestureRecognizer *oSwipeUp = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(mPreviousPage:) ] autorelease];
oSwipeUp.numberOfTouchesRequired = 2;
oSwipeUp.direction = UISwipeGestureRecognizerDirectionUp;
[self.view addGestureRecognizer:oSwipeUp];

【讨论】:

感谢您的回复。似乎您的代码与我的代码相同,只是您将 self.view 放在我放置 scrollview 的位置(我的视图的名称)。我按照你的方式试过了,应用程序似乎仍然无法识别多次触摸。这让我觉得我的代码中的其他地方在 iOS 4.3 中禁用了多点触控,但在 4.2 中没有。出于好奇,您的视图是滚动视图还是其他类型的视图? 我看到问题解决了。在回答您的问题时,我使用的是表格视图。

以上是关于手势识别器在 iOS 4.3 中停止工作的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift - 使点击手势识别器在视图下工作

使用点击手势识别器时,IOS swift应用程序无法正常工作

如何在iOS中将触摸传递给手势识别器?

如何在ios中的特定collectionview单元格上应用手势识别器

iOS 动画块手势识别器

在 iOS 7 中操作手势识别器