swift4.0

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

2018-09-21  本文已影响225人  279cb620c509

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")
        
    }
上一篇下一篇

猜你喜欢

热点阅读