美文网首页
iOS学习笔记之UIButton防止连续点击

iOS学习笔记之UIButton防止连续点击

作者: Kity_Pei | 来源:发表于2019-09-15 14:00 被阅读0次

    生活就像海洋,只有意志坚强的人,才能到达彼岸。

    前言

    为什么UIButton要防止连续点击?

    应用场景如下所示但不仅仅如此:

    由于手机性能等其他原因,用户在点击UIButton进行页面Push操作时,由于误操作连点了,导致Push多个相同页面;
    当用户点击UIButton需要请求网络,由于网络请求颇耗时,如果连续点击,意味着需要执行多次相同操作的网络请求,造成服务器资源浪费;
    防止暴力点击。

    正文

    防止UIButton连续点击的方案概述

    • 方案一:通过UIButtonenableduserInteractionEnabled两个属性来控制UIButton是否可点击。
    • 方案二:通过NSObject以下两个方法来控制UIButton的响应事件事件间隔。
      + (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:  (SEL)aSelector object:(id)anArgument;
      - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
      
    • 方案三:通过Runtime来控制UIButton的响应事件的时间间隔。

    各个方案的优缺点

    方案一
    优点:逻辑最清晰,易懂;
    缺点:由于属性值是Bool类型的,所以需要成对出现,代码书写的比较分散,容易出现异常。

    方案二

    优点:逻辑比较清晰;
    缺点:连续点击按钮时取消之前的点击事件,从而只执行最后一次点击事件,所以可能出现延迟现象,代码书写也比较分散。

    方案三

    利用Runtime使用类别来处理UIButton,代码书写比较集中,修改编辑比较方便。

    各个方案的代码实现

    方案一

    @IBAction func onClickedBtn(_ sender: UIButton) {
        sender.isEnabled = false
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(1)) {
            sender.isEnabled = true
        }
    }
    

    方案二

    @IBAction func onClickedBtn(_ sender: UIButton) {
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(onClickedBtn(_:)), object: sender)
        self.perform(#selector(onClickedBtn(_:)), with: sender, afterDelay: 2.0)
    }
    

    方案三

    public extension UIButton {
        private struct AssociatedKeys {
            static var eventInterval = "eventInterval"
            static var eventUnavailable = "eventUnavailable"
        }
    
        /// 重复点击的时间 属性设置
        var eventInterval: TimeInterval {
            get {
                if let interval = objc_getAssociatedObject(self, &AssociatedKeys.eventInterval) as? TimeInterval {
                    return interval
                }
                return 0.5
            }
            set {
                objc_setAssociatedObject(self, &AssociatedKeys.eventInterval, newValue as TimeInterval, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    
        /// 按钮不可点 属性设置
        private var eventUnavailable : Bool {
            get {
                if let unavailable = objc_getAssociatedObject(self, &AssociatedKeys.eventUnavailable) as? Bool {
                    return unavailable
                }
                return false
            }
            set {
                objc_setAssociatedObject(self, &AssociatedKeys.eventUnavailable, newValue as Bool, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    
        /// 新建初始化方法,在这个方法中实现在运行时方法替换
        class func initializeMethod() {
            let selector = #selector(UIButton.sendAction(_:to:for:))
            let newSelector = #selector(new_sendAction(_:to:for:))
            
            let method: Method = class_getInstanceMethod(UIButton.self, selector)!
            let newMethod: Method = class_getInstanceMethod(UIButton.self, newSelector)!
            
            if class_addMethod(UIButton.self, selector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)) {
                class_replaceMethod(UIButton.self, newSelector, method_getImplementation(method), method_getTypeEncoding(method))
            } else {
                method_exchangeImplementations(method, newMethod)
            }
        }
    
        /// 在这个方法中
        @objc private func new_sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
            if eventUnavailable == false {
                eventUnavailable = true
                new_sendAction(action, to: target, for: event)
                // 延时
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + eventInterval, execute: {
                    self.eventUnavailable = false
                })
            }
        }
    }
    

    注意:
    如果是使用方案三的话,由于在Swift 4中的initialize()已经被废弃,所以需要在AppDelegate调用自己写的initializeMethod()方法。

    相关文章

      网友评论

          本文标题:iOS学习笔记之UIButton防止连续点击

          本文链接:https://www.haomeiwen.com/subject/fgjdyctx.html