防止 UIButton 的連續(xù)點(diǎn)擊,無非就是網(wǎng)上那三種方法,前兩種即手動設(shè)置 isEnabled、或者在點(diǎn)擊的時候取消未執(zhí)行的事件,再延時執(zhí)行。這里重點(diǎn)說一下第三種,即重寫 load 方法,在 load 方法的時候利用 runtime 將方法交換一下,將 sendAction 方法與自定義的 sendAction 方法交換,在自定義的方法中實(shí)現(xiàn)防止連續(xù)點(diǎn)擊的目的。
但是由于我們項(xiàng)目使用的是 swift 語言,在 swift 中已經(jīng)廢除了 load 方法,所以只能嘗試其他方法,我嘗試了一下后發(fā)現(xiàn)直接重寫 sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) 即能達(dá)到目的,不必使用方法交換。具體代碼如下:
// 設(shè)置的點(diǎn)擊間隔
var acceptEventInterval: TimeInterval {
set {
objc_setAssociatedObject(self, &UIButtonObjectKeys.acceptEventInterval, newValue, .OBJC_ASSOCIATION_RETAIN)
}
get {
return (objc_getAssociatedObject(self, &UIButtonObjectKeys.acceptEventInterval) as? TimeInterval) ?? 0.0
}
}
// 儲存的上一次點(diǎn)擊時間
private var acceptEventTime: TimeInterval {
set {
objc_setAssociatedObject(self, &UIButtonObjectKeys.acceptEventTime, newValue, .OBJC_ASSOCIATION_RETAIN)
}
get {
return (objc_getAssociatedObject(self, &UIButtonObjectKeys.acceptEventTime) as? TimeInterval) ?? 0.5
}
}
open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
// 如果這次點(diǎn)擊時間減去上次點(diǎn)擊事件小于設(shè)置的點(diǎn)擊間隔,則不執(zhí)行
if Date().timeIntervalSince1970 - self.acceptEventTime < self.acceptEventInterval {
return
}
// 存儲最后一次點(diǎn)擊執(zhí)行的時間
if self.acceptEventInterval > 0 {
self.acceptEventTime = Date().timeIntervalSince1970
}
// 執(zhí)行action
super.sendAction(action, to: target, for: event)
}
最后說一下在用的時候發(fā)現(xiàn)的一個小 bug,就是我們項(xiàng)目中的一個按鈕在為 touchUpInside 添加了兩個 action,而我設(shè)置的acceptEventInterval點(diǎn)擊間隔默認(rèn)為 1.0,在此時由于兩次 action 執(zhí)行的時間間隔可以忽略不計,此時只能執(zhí)行一個 action,在這個要注意一點(diǎn),就是acceptEventInterval時間間隔最好設(shè)置默認(rèn)為 0,需要防止重復(fù)點(diǎn)擊的 Button 設(shè)置為 1.0,以防止在使用的時候出現(xiàn)問題,當(dāng)然也可以酌情設(shè)置,或者在sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) 方法中利用判斷 action、target、event 等屬性來解決這個事情,此處不予深究。