【问题标题】:Prevent multiple Tap on the same UIButton防止多次点击同一个 UIButton
【发布时间】:2016-05-20 08:34:32
【问题描述】:

在我的应用程序中有时我会收到此错误,因为 UI 冻结并且用户多次点击按钮:

"多次推送同一个视图控制器实例不是 支持”

我试过这个:

How to prevent multiple event on same UIButton in iOS?

它就像一个魅力,但如果我的标签栏有超过 5 个元素,如果我点击显示大于 5 的元素的按钮,则更多的按钮从左到右动画。

有没有其他不使用动画的简单方法来防止双标签?

这是我正在使用的代码:

- (IBAction)btnAction:(id)sender {
    UIButton *bCustom = (UIButton *)sender;
    bCustom.userInteractionEnabled = NO;
    [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionAllowAnimatedContent animations:^{
        [self selectTabControllerIndex:bCustom.tag];
    } completion:^(BOOL finished){
        bCustom.userInteractionEnabled = YES;
    }];
}

【问题讨论】:

标签: ios objective-c uibutton


【解决方案1】:

首先提示,如果您只有按钮调用该选择器,您可以将id 更改为UIButton* 并删除额外变量bCustom

现在,要解决您的问题,您只需确保在完成其他任何您需要做的事情后将userInteractionEnabled 转回YES。使用动画块只是一种简单的方法,因为它内置了一个完成处理程序。

您只需让selectTabControllerIndex 方法为您完成这项工作即可。

类似这样的:

- (IBAction)btnAction:(UIButton*)sender {
    sender.userInteractionEnabled = NO;
    [self selectTabControllerForButton:sender];
}

- (void)selectTabControllerForButton:(UIButton*)sender {
    // Whatever selectTabControllerIndex does now goes here, use sender.tag as you used index
    sender.userInteractionEnabled = YES;
}

如果您之后可能需要执行其他代码,则可以将完成处理程序添加到您的 selectTabControllerIndex 方法中,然后调用完成处理程序。在其中您将包含sender.userInteractionEnabled = YES; 行。但如果始终使用相同的代码,第一种方法更简单、更快捷。

【讨论】:

    【解决方案2】:

    使用userInteractionEnable=false 防止双击就像使用火箭发射器杀死蜜蜂一样。

    相反,您可以使用myButton.enabled=false。使用它,您可以更改(如果需要)按钮在停用时的布局。

    【讨论】:

    • 你能解释一下 userInteractionEnable= false 有什么问题
    • 问题是userInteractionEnable是视图属性,myButton.enabled=false是UIButton属性。因此,您始终应该使用 Apple 为您提供的方式来实现您的目标。
    • 请注意,使用enabled 属性还有其他在这种情况下不需要的副作用。这些是 UI 更改,例如更改按钮上的颜色、文本、图像,以向用户指示按钮已禁用。这意味着当按钮被禁用并在不久之后再次启用时,您会得到一种闪光,这可能会分散/混淆用户的注意力。另外,请不要杀死蜜蜂。 :)
    【解决方案3】:

    Swift中,你也可以使用defer关键字来执行一段代码,该代码块只有在执行离开当前作用域时才会执行。

    @IBAction func btnAction(_ sender: UIButton) {
        sender.isUserInteractionEnabled = false
        defer {
            sender.isUserInteractionEnabled = true
        }
        // rest of your code goes here
    }
    

    注意:这只有在“其余代码”不是async 时才有用,这样执行实际上会离开当前范围。 在异步情况下,您需要在该异步方法的末尾设置 isUserInteractionEnabled = true

    【讨论】:

    • 在我点击按钮时显示动画的情况下工作。谢谢
    【解决方案4】:

    在某些情况下禁用 isUserInteractionEnabled 或禁用按钮不起作用,如果在下一个控制器中有后台 API 调用,推送过程将异步工作。

    经过一些工作,我认为最好采用另一种方式,我在 Objective-CClosure 中找到了 Completion handler Swift 在这里可以做得很好。

    这是我在 Objective c 中使用的示例:

     -(void)didSettingClick:(id) sender
    {
        if (!isPushInProcess) {
                 isPushInProcess = YES;
                SettingVC *settings = [[SettingVC alloc] initWithcomplition:^{
                   isPushInProcess = NO;
                }];
                [self.navigationController pushViewController:settings animated:YES];
               }
    
    }
    

    这里是方法说明:

    dispatch_block_t pushComplition;
    
    -(instancetype) initWithcomplition:(dispatch_block_t)complition{
        self = [super init];
        if (self) {
            pushComplition = complition;
        }
        return self;
    }
    

    viewDidAppear() 内部

    -(void)viewDidAppear:(BOOL)animated
    {
        pushComplition();
    }
    

    在 swift 中使用 defer 关键字也是个好主意。

    希望对你有帮助!!!

    【讨论】:

      【解决方案5】:

      您可以在用户第一次点击时禁用该按钮的 userInteraction。

      然后会出现新的视图控制器,同时留给新的视图控制器调用这个

       -(IBAction)btnAction:(UIButton *)sender {
         sender.userInteractionEnabled=NO;
        //do your code
        }
      

      如果它正在移动到另一个视图然后调用下面的一个

       -(void)viewWillDisappear {
        buttonName.userInteractionEnabled=YES;
       }
      

      如果不从当前视图移动 你可以打电话

        sender.userInteractionEnabled=YES;
      

      在 btnAction 方法的末尾。

      它肯定会起作用。

      【讨论】:

        【解决方案6】:
        myButton.multipleTouchEnabled = NO;
        

        【讨论】:

        • 请添加一些您认为这会有所帮助的解释。只贴一行代码是不行的。
        • 它对我不起作用。我仍然可以双击
        • 这行不通,因为问题是关于多次点击,而不是触摸!
        【解决方案7】:

        Swift 4 版本的 @Santo 答案对我有用:

        按钮代码:

        @IBAction func btnMapTap(_ sender: UIButton) {
        
            sender.isUserInteractionEnabled = false
        
            //put here your code 
        

        添加覆盖方法viewWillDisappear:

        override func viewWillDisappear(_ animated: Bool) {
            btnMap.isUserInteractionEnabled = true
        }
        

        【讨论】:

          【解决方案8】:

          使用此代码:这是布尔条件

          button.ismultipleTouchEnabled = false
          

          【讨论】:

            【解决方案9】:

            似乎在iOS 14.x下,当你点击时它会自动发生。

            我编写了一个带有导航控制器的小型演示应用程序,这是一个“ViewController”类的控制器,带有一个调用“pushIt”动作的按钮。

            (见代码) 我已将 Storyboard ID 设置为单独的控制器以“ColoredVCID”并添加了一个全局计数器,只是为了查看...

            Long way SHORT:它似乎正常工作。

            //  compulsiveTouch
            //
            //  Created by ing.conti on 03/08/21.
             
               import UIKit
                
                fileprivate var cont = 0
                
                class ViewController: UIViewController {
                
                    @IBAction func pushIt(_ sender: Any) {
                        
                        cont+=1
                        print(cont)
                
                        let storyboard = UIStoryboard(name: "Main", bundle: nil)
                        let vc = storyboard.instantiateViewController(withIdentifier: "ColoredVCID")
                        self.navigationController!.present(vc, animated: true)
                        // OR:
                        self.navigationController!.pushViewController(vc, animated: true)
                    }
                
                }
            

            过去天我通常会这样做:

               @objc func pushItOLD(_sender: Any){
            
                    // prevent compulsive touch:
                    self.setButtonActive(btn: self.pushBtn!, active: false)
                    // now re-eanble it... after 1 second:
                    let when = DispatchTime.now() + 1
                    DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
            
                        self.setButtonActive(btn: self.pushBtn!, active: true)
                    })
            
            
                }
                
                func setButtonActive(btn: UIButton?,  active: Bool){
                    guard let btn = btn else{
                        return
                    }
                    btn.isEnabled = active
                    btn.alpha = (active ? 1 : 0.5)
                }
            

            如果您的按钮例如调用网络请求...以防止重复调用,那么这在当今非常有用。

            (我添加了一些化妆品来使用 alpha.. 让用户将其视为“已禁用”..)

            【讨论】:

              【解决方案10】:

              我是这样做的

              var callInProgress = false
              
              
              func call(){
              
                 if callInProgress == true{
                   return
                 }
              
                 callInProgress = true
              
                //Make it false when your task done
              
              }
              

              在您将 callInProgress 设为 false 之前,它不允许用户再次调用该函数

              这是唯一有效的方法

              【讨论】:

                猜你喜欢
                • 2013-05-18
                • 2014-11-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-12-11
                • 1970-01-01
                相关资源
                最近更新 更多