IOS/Objective-C/Autolayout:在视图上滑动手势只工作一次,然后通过滑动来移动视图

Posted

技术标签:

【中文标题】IOS/Objective-C/Autolayout:在视图上滑动手势只工作一次,然后通过滑动来移动视图【英文标题】:IOS/Objective-C/Autolayout: Swipe gesture on view only working once and then view moves with swipe 【发布时间】:2018-03-23 18:23:22 【问题描述】:

我正在尝试调试一个奇怪的问题。我有创建 leftswiperecognizer 的代码,将其分配给视图,并有一个处理程序可以在滑动时更改某些元素。

我有这个代码的版本可以正常工作。然而,在一个 VC 上,在第一次滑动后也可以正常工作,在第二次滑动时,不是手势被识别,而是整个视图移动 - 就好像您正在拖动它或尝试水平滚动它一样。存在一个滚动识别器,但通常它只响应垂直拖动。此屏幕上还有一个点击识别器。他们都工作正常。同一个应用程序的其他屏幕,左滑、滚动和点击识别器都可以正常运行。

简而言之,第一次刷卡效果很好。然后没有识别到​​滑动。以前有人遇到过这个问题吗?提前感谢您的任何建议。

//create recognizer (called from viewdidload)
-(void) addLeftSwipeRecognizer 
    UISwipeGestureRecognizer *recognizer;
    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipe:)];
    [recognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
    [[self view] addGestureRecognizer:recognizer];


- (void) handleLeftSwipe:(UISwipeGestureRecognizer *) sender

    self.title = @"New title";
//some other changes to labels.
    

//other recognizers
called from viewdidload    
-(void) addListTapRecognizer 
    UITapGestureRecognizer *tapList = [[UITapGestureRecognizer alloc]initWithTarget:self     action:@selector(handleTap:)];
      tapList.cancelsTouchesInView = NO;
    self.listSub.userInteractionEnabled=YES;
    self.listSub.editable=NO;
    [self.listSub addGestureRecognizer:tapList];

- (void) handleTap:(UITapGestureRecognizer *)recognizer

    UITextView *textView =  (UITextView *)recognizer.view;
    CGPoint location = [recognizer locationInView:textView];

    CGPoint position = CGPointMake(location.x, location.y);
     UITextPosition *tapPosition = [textView closestPositionToPoint:position];
//do some stuff based on position of tap

//called from viewdidload
-(void) addScrollGestureRecognizer 
    UITapGestureRecognizer *tapScroll = [[UITapGestureRecognizer alloc]initWithTarget:self     action:@selector(tapped)];
    tapScroll.cancelsTouchesInView = NO;
    self.scrollView.userInteractionEnabled =YES;
    [self.scrollView addGestureRecognizer:tapScroll];

//dismiss keyboard when you tap scrollview
- (void) tapped

    [self.view endEditing:YES];

【问题讨论】:

“然而,在一个 VC 上,在第一次滑动也可以正常工作之后,在第二次滑动时,不是手势被识别,而是整个视图移动”所以显而易见的问题是:有什么特别之处那个VC?例如,它是否在页面视图控制器中?在导航控制器中?它必须在一些特殊的环境中,与其他环境不同。 它与 tableVC 的 Detail VC 非常相似。 handletap 识别器比其他点击识别器更复杂。但是,当您拖动视图时,不会触发任何手势识别器。其他事情正在发生。 【参考方案1】:

在第二次滑动时,不是识别手势,而是整个视图移动

为了便于讨论,我们假设您所做的一切都是正确的,并且没有将滑动手势识别器添加到错误的视图中。那么,这意味着“整个视图”有一个手势识别器,可能是滑动或平移手势识别器,它首先识别并导致您的手势识别器失败。

您可以通过询问该视图的gestureRecognizers 轻松找到这一点。这是一个实用方法,可让您向视图询问其所有手势识别器及其父视图的所有手势识别器,因为它们会影响此视图:

extension UIView 
    func reportAllGestureRecognizers() 
        if let grs = self.gestureRecognizers 
            print(grs)
        
        if let sup = self.superview 
            sup.reportAllGestureRecognizers()
        
    

在您的视图进入界面后的某个时间点(即在viewDidAppear 之后),将该消息发送到某个视图,例如self.view.reportAllGestureRecognizers。你可能会对你学到的东西感到惊讶。

如果是这样的话,有委托方法和其他设备可以让你在你的手势识别器和另一个手势识别器之间进行调解,以便你的识别器首先识别。

【讨论】:

谢谢,将 swift 翻译成 obj-c 需要一些时间,但我会尝试一下。 抱歉,没有注意到这是Objective-C。但是你明白了:它是 UIView 上的一个类别,具有一个实例方法,NSLogs [self gestureRecognizers] 然后在 [self superview] 上调用相同的方法。在 Objective-C 中,如果 superview 是 nil 将无害地失败,因此递归将结束。

以上是关于IOS/Objective-C/Autolayout:在视图上滑动手势只工作一次,然后通过滑动来移动视图的主要内容,如果未能解决你的问题,请参考以下文章