- 通過擴展(Extension)實現UIButton倒計時
extension UIButton {
//取消倒計時
func cancel(backgroundColor: UIColor) {
DispatchQueue.main.async(execute: {
self.isEnabled = true
self.backgroundColor = backgroundColor
self.timer?.cancel()
self.timer = nil
})
}
struct Key {
static var timerKey = "timerKey"
}
//通過關聯屬性給UIButton添加一個timer屬性,主要用來取消定時
var timer: DispatchSourceTimer? {
// 在調用DispatchSourceTimer時, 無論設置timer.scheduleOneshot, 還是timer.scheduleRepeating代碼 不調用cancel(), 系統會自動調用
// 另外需要設置全局變量引用, 否則不會調用事件
get {
return objc_getAssociatedObject(self, &Key.timerKey) as? DispatchSourceTimer
}
set {
objc_setAssociatedObject(self, &Key.timerKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
/// 開始button倒計時
/// - Parameters:
/// - duration: 倒計時時間:單位秒
/// - disableBackGroudColor: button不可點擊時背景顏色
/// - disableBackGroudColor: button不可點擊時字體顏色
func startSMSWithDuration(duration: Int, disableBackGroudColor: UIColor = .gray,disableTitleColor: UIColor = .white) {
var times = duration
let normalBGColor = backgroundColor
//初始化Timer
timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
//timer事件處理
timer?.setEventHandler {
if times > 0 {
//倒計時處理
DispatchQueue.main.async(execute: {
self.isEnabled = false
self.setTitle("重新獲取\(times)", for: .disabled)
self.setTitleColor(disableTitleColor, for: .disabled)
self.backgroundColor = disableBackGroudColor
times -= 1
})
} else {
//倒計時結束,取消定時,button變爲倒計時前樣式,可點擊
DispatchQueue.main.async(execute: {
self.isEnabled = true
self.backgroundColor = normalBGColor
self.timer?.cancel()
self.timer = nil
})
}
}
timer?.schedule(deadline: .now(), repeating: .seconds(1), leeway: .milliseconds(100))
timer?.resume()
}
}
2.使用(一行代碼輕鬆搞定)
//開啓定時
button.startSMSWithDuration(duration: 60, disableBackGroudColor: .darkGray, disableTitleColor: .white)
//取消定時
button.cancel(backgroundColor: .white)