【问题标题】:How to remove gesture recogniser如何删除手势识别器
【发布时间】:2012-06-12 11:05:16
【问题描述】:

所以,我将手势识别器添加到覆盖视图中。当点击屏幕时,我希望这个覆盖消失。话虽如此,添加手势识别器会覆盖“内部修饰”和其他按钮单击事件。我需要这个,因此我需要删除gesturerecognizer。我可以使用这种方法,但是我有问题。我的代码如下 -

- (void)helpClicked
{
    CGRect visibleBounds = [self convertRect:[self bounds] toView:viewContainer];
    CGFloat minimumVisibleX = CGRectGetMinX(visibleBounds);
    UIImageView * helpOverlay = [[UIImageView alloc]initWithFrame:CGRectMake(minimumVisibleX, 0, 1024, 768)];
    UIImage * helpImage = [UIImage imageNamed:@"HelpOverLay.png"];
    [helpOverlay setImage:helpImage];
    helpOverlay.tag = 50;
    self.scrollEnabled = NO;
    [self addSubview:helpOverlay]; 
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] 
                               initWithTarget:self
                               action:@selector(dismissView)];

[self addGestureRecognizer:tap];    

}

在这里,我将覆盖从另一个视图中移除。

- (void) dismissView
{
    UIView *overlay = [self viewWithTag:50];
    [overlay removeFromSuperview];
    self.scrollEnabled = YES;
}

我的问题是如何在第二种方法中删除手势识别器?我不能将变量 tap 传递给这个方法,也不能在以前的方法中删除它。任何指针?在事件方面,我遇到了很多传递变量问题。

【问题讨论】:

  • 您可以保留对tap 的引用(可能是ivar),以便您可以随时安全地删除它。

标签: iphone objective-c ios ipad ios4


【解决方案1】:

此循环将删除视图具有的所有手势识别器

for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
    [self.view removeGestureRecognizer:recognizer];
}

【讨论】:

  • 正确答案,无需使用var来保留手势... tks
  • 为什么不应该这样? for (UIGestureRecognizer *recognizer in self.view.window.gestureRecognizers) { [self.view.window removeGestureRecognizer:recognizer]; }
  • 这是正确答案。我在 SpriteKit 游戏中使用手势,当出现新场景时,识别器仍然有效。当他们在新场景中找不到目标时导致崩溃。
  • 这也会删除表格视图的滚动手势和标准 iOS 控制器添加的任何其他手势,所以要小心。
【解决方案2】:

来自WWDC 2015, Cocoa Touch Best Practices,建议您保留一个属性或iVar,如果您以后需要访问它,请不要使用viewWithTag:

Moto:属性而不是标签

这样可以省去一些麻烦:

  1. 在处理多个手势时,您可以通过访问属性直接移除您想要的手势并将其移除。 (无需迭代所有视图的手势来移除正确的手势)
  2. 在迭代时通过标签找到正确的手势,当视图上有多个标签以及与特定标签发生冲突时会非常误导

(即)您第一次使用标签实现了它,一切正常 正如预期的那样。稍后您将处理另一个功能,可以说 打破这一点并导致您不期望的不良行为。日志 不会给你一个警告,你能得到的最好的东西取决于它是一个崩溃信号无法识别的选择器发送到实例的情况。 有时你不会得到任何这些

解决方案

声明 iVar

@implementation YourController {
    UITapGestureRecognizer *tap;
}

设置视图

- (void) helpClicked {
    //Your customization code

    //Adding tap gesture
    tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissView)];
    [self addGestureRecognizer:tap];
}

直接移除手势

- (void) dismissView {
    [self.view removeGestureRecognizer:tap];
}

【讨论】:

    【解决方案3】:

    在您的@interface 中声明ivar UITapGestureRecognizer *tap

    helpClicked 更改为:

    - (void)helpClicked
    {
        CGRect visibleBounds = [self convertRect:[self bounds] toView:viewContainer];
        CGFloat minimumVisibleX = CGRectGetMinX(visibleBounds);
        UIImageView * helpOverlay = [[UIImageView alloc]initWithFrame:CGRectMake(minimumVisibleX, 0, 1024, 768)];
        UIImage * helpImage = [UIImage imageNamed:@"HelpOverLay.png"];
        [helpOverlay setImage:helpImage];
        helpOverlay.tag = 50;
        self.scrollEnabled = NO;
        [self addSubview:helpOverlay]; 
        tap = [[UITapGestureRecognizer alloc] 
                                   initWithTarget:self
                                   action:@selector(dismissView)];
    
        [self addGestureRecognizer:tap];  
    }
    

    dismissView 到:

    for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
        [self removeGestureRecognizer:tap];
    }
    

    编辑:我认为 nhahtdh 的方法比这个更优雅。

    EDIT2:看来你有 [self addGestureRecognizer:tap] 在工作,所以我推测这是 UIView 的子类。

    【讨论】:

    • 您好,根据某些事件继续在视图中添加和删除手势是否足够公平?请告诉我。
    • @Searching:这通常是“快速而肮脏”的解决方案,具有更好、更优雅的替代方案。这真的取决于 UI。
    • 感谢您的评论。请你给我一些例子,因为当我添加 Tapgesture 时按钮不起作用。
    • 我想你应该发布一个问题,描述你的问题和你正在使用的代码。想到的一个问题是按钮已经在自己处理触摸,而这种触摸可能永远不会到达您的手势识别器。
    【解决方案4】:

    Swift 版本:

    if let recognizers = yourView.gestureRecognizers { 
      for recognizer in recognizers {
        yourView.removeGestureRecognizer(recognizer)
      }
    }
    

    【讨论】:

      【解决方案5】:

      只需设置一次覆盖视图,并设置手势识别器,但将覆盖视图隐藏。当视图被隐藏时,它不会收到用户的任何触摸。仅在必要时使覆盖视图可见,并在不需要时将其隐藏。

      【讨论】:

        【解决方案6】:

        对于第二种方法,您的代码应该看起来更像这样:

        - (void) dismissView {
          UIView *overlay = [self viewWithTag:50];
        
          for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
            if([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
              [self removeGestureRecognizer:recognizer];
            }
          }
        
          [overlay removeFromSuperview];
          self.scrollEnabled = YES;
        }
        

        我添加了对 UITapGestureRecognizer 的检查,以防您的班级处理超过 1 个 UIGestureRecognizers 而您只想删除它。

        【讨论】:

          【解决方案7】:

          这对我有用:

          for (UIGestureRecognizer *gr in self.view.gestureRecognizers) {
            [self.view removeGestureRecognizer:gr];
          }
          

          【讨论】:

            【解决方案8】:

            在 Swift 4 中

            if let gestures = shotButton.gestureRecognizers //first be safe if gestures are there
                {
                    for gesture in gestures //get one by one
                    {
                        shotButton.removeGestureRecognizer(gesture) //remove gesture one by one
                    }
                }
            

            【讨论】:

              【解决方案9】:

              如果您能够扩展视图,您可以尝试这种方式:

              _ = gestureRecognizers.flatMap { $0.map { removeGestureRecognizer($0) } }
              

              【讨论】:

                【解决方案10】:

                它对我有用。

                while (view.gestureRecognizers.count) {
                  [view removeGestureRecognizer:[view.gestureRecognizers objectAtIndex:0]];
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-11-30
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-12-08
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多