iOS開發中經常需要使用計時器。比如驗證碼倒計時等,所以今天總結一下iOS的計時器操作。
NSTimer 計時器
NSTimer是常用的計時器方案,主要是可以簡單快速的創建一個Timer對象來進行操作。官方API如下:
// 創建方法1
open class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
// 創建方法2
public init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)
// 銷毀方法。銷毀之后要將Timer對象設置為nil。
open func invalidate()
雖然 NSTimer 是很常用的計時器,但是 NSTimer 如果和 ScrollView 同時使用的情況下,會造成 ScrollView 滑動時 Timer 停止運行,原因是 NSTimer 和 ScrollView 不在同一個 RunloopMode 下造成的。解決 ScrollView 和 Timer 沖突的方案為,將 NSTimer 加入到 Runloop 的 CommonModes 中。實例代碼如下:
RunLoop.current.add(timer, forMode: RunLoop.Mode.common)
GCD 計時器
GCD 計時器和 Timer 計時器一樣也是常用的一種計時器。Timer 計時器在運行時受 Runloop 的影響,但是 GCD 計時器不受 Runloop 的影響,可以讓計數更加准確。
GCD 計時器示例代碼如下:
var timer: DispatchSourceTimer?
...
var count = 1
timer = DispatchSource.makeTimerSource(flags: [], queue: nil)
timer?.schedule(deadline: .now(), repeating: 1)
timer?.setEventHandler {
print("count = \(count)")
count += 1
if count >= 60 {
self.timer?.cancel() // 停止計時器
}
}
timer?.resume()
CADisplayLink
CADisplayLink 是一個能讓我們以和屏幕刷新率相同的頻率將內容畫到屏幕上的定時器。在應用中創建一個 CADisplayLink 對象,將CADisplayLink對象添加到 Runloop 中后,計時器就會啟動,執行了 invalidate
函數之后。CADisplayLink 對象就會從 Runloop 中移除,selector 也會停止調用。
示例代碼如下:
link = CADisplayLink(target: self, selector: #selector(countDown))
link?.preferredFramesPerSecond = 1 // 間隔時間
link!.add(to: RunLoop.current, forMode: .default) // 添加到 Runloop