在iOS中有3種常見的定時器,它們會根據不同的場景進行選擇使用。
1.DispatchSourceTimer: 基於GCD實現。
2.CADisplayLink:基於螢幕重新整理實現。
3.Timer:基於RunLoop實現。
DispatchSourceTimer定時器
DispatchSourceTimer定時器可以透過DispatchSource.makeTimerSource(queue: DispatchQueue.main)方法來建立,並且
使用GCD建立了一個DispatchSource型別的定時器,並使用全域性佇列來執行它。透過schedule(deadline: .now(), repeating: .seconds(1))方法指定定時器的初始延遲和重複時間,然後設定了一個事件處理程式來定義定時器要執行的操作。
最後timer.resume()啟動定時器。
要停止定時器,可以呼叫timer.cancel()方法。
優點為:Dispatch定時器非常輕量級,基於GCD的實現,可以利用GCD的優勢來進行任務排程,效能高。
var timer: DispatchSourceTimer? func startCountdown() { //一般倒數計時是操作UI,使用主佇列 timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main) // //耗時操作放在全域性佇列,子執行緒處理 // timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global()) timer.schedule(deadline: .now(), repeating: .seconds(1)) timer.setEventHandler { // 定時器執行的操作 } timer.resume() } deinit { timer.cancel() timer = nil }
CADisplayLink定時器
CADisplayLink定時器可以透過CADisplayLink(target: self, selector: #selector(update))方法建立,並且透過displayLink.add(to: .main, forMode: .common)方法將定時器新增到主執行迴圈中,並指定了執行模式。
然後定義update方法,該方法將在每個定時器週期中執行。
在物件銷燬前停止定時器,可以呼叫displayLink.invalidate()方法。
CADisplayLink物件一旦建立就會執行,比較適合監控主執行緒UI卡頓,用做倒數計時不如使用DispatchSourceTimer
它是和螢幕重新整理率同步,優點在於精確度高,適用於需要頻繁更新UI的場景。
var displayLink: CADisplayLink? func startCountdown() { //一般倒數計時是操作UI,使用主佇列 let displayLink = CADisplayLink(target: self, selector: #selector(update)) //設定多長時間回撥一次,預設每次重新整理都會呼叫,大概60ps, 這裡設定1表示1s呼叫一次 displayLink.preferredFramesPerSecond = 1 displayLink.add(to: .main, forMode: .common) } @objc func update() { // 定時器執行的操作 } deinit { displayLink.invalidate() displayLink = nil }
Timer定時器
Timer定時器可以使用Timer.scheduledTimer方法建立,然後指定重複間隔和一個閉包作為定時器要執行的操作。並且將返回的定時器物件儲存在變數timer中。
要停止定時器,可以呼叫timer.invalidate()方法。
Timer是一個簡單的定時器,基於RunLoop的,通常用於實現對實時性要求不高的場合,因為它被註冊在runloop的timers事件源集合中,如果當前runloop執行耗時任務超過了呼叫時間,那麼就會丟棄當前次,直接執行下一次。導致定時器不準時的情況。
var timer: Timer? func startCountdown() { //一般倒數計時是操作UI,使用主佇列 timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in // 定時器執行的操作 } } deinit { timer.invalidate() timer = nil }