在開發過程當中,Timer能夠說是比較常見的了,用來作一些定時性的操做。可實際過成功,Timer的時間真的準嗎?下面寫幾個代碼來作驗證。工具
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(timerTest), userInfo: nil, repeats: true) @objc func timerTest() { print("timer info - \(Date.init())") }
運行結果:oop
timer info - 2020-10-28 05:02:33 +0000 timer info - 2020-10-28 05:02:34 +0000 timer info - 2020-10-28 05:02:35 +0000 timer info - 2020-10-28 05:02:36 +0000
看結果仍是比較準備的,不妨加大量繼續測試。在輸入時加一些耗時操做。開發工具
@objc func timerTest() { var count = 0 for index in 0..<100000 { count += 1 } print("timer info - \(Date.init())") }
再看運行結果:測試
timer info - 2020-10-28 05:04:20 +0000 timer info - 2020-10-28 05:04:21 +0000 timer info - 2020-10-28 05:04:22 +0000 timer info - 2020-10-28 05:04:23 +0000 timer info - 2020-10-28 05:04:24 +0000 timer info - 2020-10-28 05:04:25 +0000 timer info - 2020-10-28 05:04:26 +0000
還能夠嘛!結果依然看起來挺對的,那就繼續加大工做量。再測試:spa
@objc func timerTest() { var count = 0 for index in 0..<10000000 { count += 1 } print("timer info - \(Date.init())") }
看運行結果:插件
timer info - 2020-10-28 05:05:19 +0000 timer info - 2020-10-28 05:05:23 +0000 timer info - 2020-10-28 05:05:27 +0000 timer info - 2020-10-28 05:05:31 +0000
這時候結果就明顯了,我要求的定時是1秒鐘,可間隔出現了居然4秒了。這跟我要求的就相差很大了。可這是怎麼出現的呢?線程
定時器被添加在主線程中,因爲定時器在一個RunLoop中被檢測一次,因此若是在這一次的RunLoop中作了耗時的操做,當前RunLoop持續的時間超過了定時器的間隔時間,那麼下一次定時就被延後了。code
一、在子線程中建立timer,在主線程進行定時任務的操做
二、在子線程中建立timer,在子線程中進行定時任務的操做,須要UI操做時切換回主線程進行操做 blog
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in print("timer info - \(Date.init())") }
爲了驗證,咱們在當前頁面上添加一個tableview,在定時器運行時,咱們對tableview進行滑動操做,能夠發現,定時器並不會觸發下一次的定時任務。開發
主線程的RunLoop有兩種預設的模式,RunLoopDefaultMode和TrackingRunLoopMode。
當定時器被添加到主線程中且無指定模式時,會被默認添加到DefaultMode中,通常狀況下定時器會正常觸發定時任務。可是當用戶進行UI交互操做時(好比滑動tableview),主線程會切換到TrackingRunLoopMode,在此模式下定時器並不會被觸發。
添加定時器到主線程的CommonMode中或者子線程中
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(timerTest), userInfo: nil, repeats: true) // RunLoop.main.add(timer, forMode: .common)
從結果看,Timer在其使用場景下足夠準了,對於「不許」更可能是集中在對其錯誤的使用方式上,只要咱們足夠深刻了解,正確地使用,就能讓它「準」。
實際上,蘋果也不推薦使用過高精度的定時器,對於Timer,精度在50-100ms都是正常的,若是咱們須要足夠高精度地進行計時,好比統計APP啓動時間、一段任務代碼的運行時間等等,Timer不是一個好的選擇,mach_absolute_time()或者能夠幫到你,蘋果開發工具也帶有更專業的API或者插件提供給開發者。