美文网首页swift4.0
swift UIButton防止按钮重复点击(时间等候模式/事件

swift UIButton防止按钮重复点击(时间等候模式/事件

作者: 279cb620c509 | 来源:发表于2018-09-21 18:36 被阅读225次

    swift 防止按钮重复点击(时间等候模式/事件完成模式)

    关于UIButton重复点击,网上提供了很详细的设置规定时间防止重复点击的方案。但在实际项目中我们常遇到button点击异步网络请求的问题,这时我们不能知晓具体时间时最好能有变量设置判断是否允许点击,很简单的if判断就OK了

    //MARK: 防止按钮重复点击
    let defaultDuration = 3.0
    
    
    extension UIButton{
        @objc func my_sendAction(action: Selector, to target: AnyObject?, forEvent event: UIEvent?) {
    
            if (self.isKind(of: UIButton.self)) {
                
                switch self.repeatButtonClickType {
                case .durationTime:
                    clickDurationTime = clickDurationTime == 0 ? defaultDuration : clickDurationTime
                    
    
                    if isIgnoreEvent {
                        return
                    } else if clickDurationTime > 0 {
                        isIgnoreEvent = true
                        // 在过了我们设置的duration之后,再将isIgnoreEvent置为false
                        DispatchQueue.global(qos: .default).asyncAfter(deadline: DispatchTime.now() + clickDurationTime) {
                            
                            
                            self.isIgnoreEvent = false
                        }
                        
                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + clickDurationTime) {
                            self.isIgnoreEvent = false
                        }
                        
                        
                        my_sendAction(action: action, to: target, forEvent: event)
                    }
                    
                    
                case .enentDone:
                    
                    if !isFinishEvent {
                        my_sendAction(action: action, to: target, forEvent: event)
                        isFinishEvent = true
                    }
                }
     
            } else {
                my_sendAction(action: action, to: target, forEvent: event)
            }
        }
    }
    
    enum RepeatButtonClickType : Int{
        case durationTime = 0
        case enentDone
    }
    
    
    extension UIButton {
    
        private struct AssociatedKeys {
            static var clickDurationTime = "my_clickDurationTime"
            static var isIgnoreEvent = "my_isIgnoreEvent"
            static var isFinish = "my_isFinish"
            static var repeatButtonClickType = "repeatButtonClickType"
        }
    
        var repeatButtonClickType : RepeatButtonClickType {
            set {
                objc_setAssociatedObject(self, &AssociatedKeys.repeatButtonClickType, newValue as RepeatButtonClickType, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            
            get {
                
                if let clickDurationTime = objc_getAssociatedObject(self, &AssociatedKeys.repeatButtonClickType) as? RepeatButtonClickType {
                    return clickDurationTime
                }
                
                return .durationTime
            }
        }
        
        // 点击间隔时间
        var clickDurationTime : TimeInterval {
            set {
                objc_setAssociatedObject(self, &AssociatedKeys.clickDurationTime, newValue as TimeInterval, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
    
            get {
    
                if let clickDurationTime = objc_getAssociatedObject(self, &AssociatedKeys.clickDurationTime) as? TimeInterval {
                    return clickDurationTime
                }
    
                return defaultDuration
            }
        }
    
        // 是否忽视点击事件
        var isIgnoreEvent : Bool {
    
            set {
                objc_setAssociatedObject(self, &AssociatedKeys.isIgnoreEvent, newValue as Bool, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
    
            get {
    
                if let isIgnoreEvent = objc_getAssociatedObject(self, &AssociatedKeys.isIgnoreEvent) as? Bool {
                    return isIgnoreEvent
                }
    
                return false
            }
        }
    
    
        // 是否完成点击事件
        var isFinishEvent : Bool {
            
            set {
                objc_setAssociatedObject(self, &AssociatedKeys.isFinish, newValue as Bool, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            
            get {
                
                if let isFinishEvent = objc_getAssociatedObject(self, &AssociatedKeys.isFinish) as? Bool {
                    return isFinishEvent
                }
                
                return false
            }
        }
    
         public class func initializeOnceMethod() {
    
    
            if self !== UIButton.self {
                return
            }
    
            DispatchQueue.once(token: "jcgf.swift-Carsh-test-Crash"){
    
                let originalSelector = #selector(UIButton.sendAction)
                let swizzledSelector = #selector(UIButton.my_sendAction(action:to:forEvent:))
    
                let originalMethod = class_getInstanceMethod(self, originalSelector)
                let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
    
                // 运行时为类添加我们自己写的my_sendAction(_:to:forEvent:)
                let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
    
                if didAddMethod {
                    // 如果添加成功,则交换方法
                    class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
                } else {
                    // 如果添加失败,则交换方法的具体实现
                    method_exchangeImplementations(originalMethod!, swizzledMethod!)
                }
            }
    
    
    
            }
    
    
    }
    
    extension DispatchQueue {
        
        private static var _onceTracker = "Stringss"
        
        public class func once(token: String, block: () -> ()) {
            
            objc_sync_enter(self)
            
            defer {
                
                objc_sync_exit(self)
                
            }
            
            if _onceTracker.contains(token) {
                
                return
                
            }
            
            _onceTracker.append(token)
            
            block()
            
        }
    
        func async(block: @escaping ()->()) {
            
            self.async(execute: block)
            
        }
    
        func after(time: DispatchTime, block: @escaping ()->()) {
            
            self.asyncAfter(deadline: time, execute: block)
            
        }
        
    }
    

    使用示例:

     override func viewDidLoad() {
            super.viewDidLoad()
      
            button = UIButton.init(type: .custom)
    
            button?.frame = CGRect(x: 0, y: 500, width: 200, height: 50)
            button?.setTitleColor(.red, for: .normal)
            button?.setTitle("haha", for: .normal)
            view.addSubview(button!)
           
            button?.addTarget(self, action: #selector(buttonClick), for: UIControlEvents.touchUpInside)
            UIButton.initializeOnceMethod()
       
           //默认是3秒内不能重复点击,加入下面代码则表示进入等待点击事件执行到输出isFinishEvent = false
           button?.repeatButtonClickType = .enentDone
            
        }
        
        @objc func buttonClick()  {
            DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 10) {
                self.button?.isFinishEvent = false
            }
            print("55667")
            
        }
    

    相关文章

      网友评论

        本文标题:swift UIButton防止按钮重复点击(时间等候模式/事件

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