iOS DispatchSourceTimer 定時器的具體使用
1. 概述
說起計(jì)時器,很多開發(fā)人員第一時間就會想起Timer,但是隨著使用的深入,慢慢就發(fā)現(xiàn)Timer其實(shí)不是很好用,比如說TableView滑動時候不執(zhí)行,Timer循環(huán)應(yīng)用。
2. DispatchSourceTimer
DispatchSourceTimer,也就是大家通常叫的GCD Timer,是依賴于GCD的一種Timer,Runloop的底層代碼中也用到這種Timer,可見GCD Timer并不依賴與Runloop。
先看一下蘋果的定義:
A dispatch source that submits the event handler block based on a timer.
2.1 GCD Timer 創(chuàng)建
使用下面的方法即可創(chuàng)建一個DispatchSourceTimer對象。
class func makeTimerSource(flags: DispatchSource.TimerFlags = [], queue: DispatchQueue? = nil) -> DispatchSourceTimer // 默認(rèn)在主隊(duì)列中調(diào)度使用 let timer = DispatchSource.makeTimerSource() // 指定在主隊(duì)列中調(diào)度使用 let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main) // 指定在全局隊(duì)列中調(diào)度使用 let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global()) // 指定在自定義隊(duì)列中調(diào)度使用 let customQueue = DispatchQueue(label: "customQueue") let timer = DispatchSource.makeTimerSource(flags: [], queue: customQueue)
2.2 GCD Timer 配置
配置Timer參數(shù),需要使用DispatchSourceTimer協(xié)議的方法??梢园才乓淮位蚨啻斡|發(fā)的Timer。Timer每次觸發(fā)的時候,都會調(diào)用已部署的任務(wù)。
// 從現(xiàn)在開始,每秒執(zhí)行一次。 timer?.schedule(deadline: DispatchTime.now(), repeating: .seconds(1), leeway: .nanoseconds(1)) // 5秒之后執(zhí)行任務(wù),不重復(fù)。 timer?.schedule(deadline: DispatchTime.now() + 5, repeating: .never, leeway: .nanoseconds(1))
2.3 GCD Timer 部署任務(wù)
當(dāng)Timer配置完參數(shù)后,使用DispatchSourceProtocol協(xié)議的方法來部署要執(zhí)行的任務(wù)。
setEventHandler和setRegistrationHandler的區(qū)別:
- setEventHandler:給Timer設(shè)置要執(zhí)行的任務(wù),包括一次性任務(wù)和定時重復(fù)的任務(wù)。回調(diào)方法在子線程中執(zhí)行。
- setRegistrationHandler:這個方法設(shè)置的任務(wù)只會執(zhí)行一次,也就是在Timer就緒后開始運(yùn)行的時候執(zhí)行,類似于Timer開始的一個通知回調(diào)。回調(diào)方法在子線程中執(zhí)行。
例如下面的代碼:
var timer: DispatchSourceTimer? func initTimer() { // 默認(rèn)在主隊(duì)列中調(diào)度使用 timer = DispatchSource.makeTimerSource() // 從現(xiàn)在開始,每秒執(zhí)行一次。 timer?.schedule(deadline: DispatchTime.now(), repeating: .seconds(1), leeway: .nanoseconds(1)) // 5秒之后執(zhí)行任務(wù),不重復(fù)。
// timer?.schedule(deadline: DispatchTime.now() + 5, repeating: .never, leeway: .nanoseconds(1))
timer?.setEventHandler { DispatchQueue.main.async { print("執(zhí)行任務(wù)") } } timer?.setRegistrationHandler(handler: { DispatchQueue.main.async { print("Timer開始工作了") } }) timer?.activate() }
執(zhí)行結(jié)果如下:
2020-11-28 02:20:00 +0000 Timer開始工作了
2020-11-28 02:20:00 +0000 執(zhí)行任務(wù)
2020-11-28 02:20:01 +0000 執(zhí)行任務(wù)
2020-11-28 02:20:02 +0000 執(zhí)行任務(wù)
2.4 GCD Timer控制方法
下面看一下Timer的一下控制方法及狀態(tài):
- activate() : 當(dāng)創(chuàng)建完一個Timer之后,其處于未激活的狀態(tài),所以要執(zhí)行Timer,需要調(diào)用該方法。
- suspend() : 當(dāng)Timer開始運(yùn)行后,調(diào)用該方法便會將Timer掛起,即暫停。
- resume() : 當(dāng)Timer被掛起后,調(diào)用該方法便會將Timer繼續(xù)運(yùn)行。
- cancel() : 調(diào)用該方法后,Timer將會被取消,被取消的Timer如果想再執(zhí)行任務(wù),則需要重新創(chuàng)建。
上面的這些方法如果使用不當(dāng),很容易造成APP崩潰,下面來看一下具體注意事項(xiàng)及建議:
- 當(dāng)Timer創(chuàng)建完后,建議調(diào)用activate()方法開始運(yùn)行。如果直接調(diào)用resume()也可以開始運(yùn)行。
- suspend()的時候,并不會停止當(dāng)前正在執(zhí)行的event事件,而是會停止下一次event事件。
- 當(dāng)Timer處于suspend的狀態(tài)時,如果銷毀Timer或其所屬的控制器,會導(dǎo)致APP奔潰。
- 2020-11-28 02:20:00 +0000 Timer開始工作了
2020-11-28 02:20:00 +0000 執(zhí)行任務(wù)
2020-11-28 02:20:01 +0000 執(zhí)行任務(wù)
2020-11-28 02:20:02 +0000 執(zhí)行任務(wù)
suspend()和resume()需要成對出現(xiàn),掛起一次,恢復(fù)一次,如果Timer開始運(yùn)行后,在沒有suspend的時候,直接調(diào)用resume(),會導(dǎo)致APP崩潰。 - 使用cancel()的時候,如果Timer處于suspend狀態(tài),APP崩潰。
- 另外需要注意block的循環(huán)引用問題。
2.5 雙重循環(huán) DispatchSourceTimer
比如:我們需要一定時間情況下(數(shù)組長度*4),每隔一段時間打印對應(yīng)下標(biāo)(每個元素隔4秒打印),無限打印
在下面例子的雙重循環(huán)中使用 DispatchSourceTimer 你會發(fā)現(xiàn)print只打印了 dom some = 0 這個不是我們想要的效果
var exaltedTimer: DispatchSourceTimer? func demo { let arr = [1,2,3,4] self.exaltedTimer = DispatchSource.makeTimerSource() self.exaltedTimer?.schedule(deadline: .now(), repeating: TimeInterval(arr.count*4)) self.exaltedTimer?.setEventHandler(handler: { for (index, item) in arr.enumerated() { let timer2 = DispatchSource.makeTimerSource() timer2.schedule(deadline: .now()+4.0*CGFloat(index), repeating: .infinity) timer2.setEventHandler { DispatchQueue.main.async { print("do some = \(index)") } } timer2.activate() } }) self.exaltedTimer?.activate() }
這個是因?yàn)閠imer2使用之后就被釋放了,所以要cancel和resume配合使用,這樣就實(shí)現(xiàn)了我們想要的效果了。
var exaltedTimer: DispatchSourceTimer? var exaltedTimerArray: [DispatchSourceTimer] = [] func demo { self.exaltedTimer?.cancel() for subTimer in self.exaltedTimerArray { subTimer.cancel() } let arr = [1,2,3,4] self.exaltedTimer = DispatchSource.makeTimerSource() self.exaltedTimer?.schedule(deadline: .now(), repeating: TimeInterval(arr.count*4)) self.exaltedTimer?.setEventHandler(handler: { for (index, item) in arr.enumerated() { let timer2 = DispatchSource.makeTimerSource() timer2.schedule(deadline: .now()+4.0*CGFloat(index), repeating: .infinity) timer2.setEventHandler { DispatchQueue.main.async { print("do some = \(index)") } } self.exaltedTimerArray.append(timer2) timer2.resume() } }) self.exaltedTimer?.resume()
參考文章
https://blog.csdn.net/guoyongming925/article/details/110224064
到此這篇關(guān)于iOS DispatchSourceTimer 定時器的具體使用的文章就介紹到這了,更多相關(guān)iOS DispatchSourceTimer 定時器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
iOS UILabel 設(shè)置內(nèi)容的間距及高度的計(jì)算示例
本篇文章主要介紹了iOS UILabel 設(shè)置內(nèi)容的間距及高度的計(jì)算示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11iOS App開發(fā)中通過UIDevice類獲取設(shè)備信息的方法
UIDevice最常見的用法就是用來監(jiān)測iOS設(shè)備的電量了,然后再實(shí)現(xiàn)電池狀態(tài)通知非常方便,除此之外還有傳感器等信息的獲取,這里我們就來總結(jié)一下iOS App開發(fā)中通過UIDevice類獲取設(shè)備信息的方法:2016-07-07iOS中關(guān)于模塊化開發(fā)解決方案(純干貨)
這篇文章主要介紹了iOS中關(guān)于模塊化開發(fā)解決方案(純干貨)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09iOS開發(fā)之級聯(lián)界面(推薦界面)搭建原理
這篇文章主要為大家詳細(xì)介紹了iOS級聯(lián)界面(推薦界面)搭建原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08簡單介紹iOS開發(fā)中關(guān)于category的應(yīng)用
這篇文章主要介紹了iOS開發(fā)中關(guān)于category的應(yīng)用,代碼仍然基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-09-09IOS中快速集成短信SDK驗(yàn)證開發(fā)(SMSSDK),IOS開發(fā)中如何設(shè)置手機(jī)短信驗(yàn)證碼
這篇文章主要介紹了IOS中快速集成短信SDK驗(yàn)證開發(fā)(SMSSDK),IOS開發(fā)中如何設(shè)置手機(jī)短信驗(yàn)證碼 的相關(guān)資料,需要的朋友可以參考下2016-01-01iOS粒子路徑移動效果 iOS實(shí)現(xiàn)QQ拖動效果
這篇文章主要為大家詳細(xì)介紹了iOS粒子路徑移動效果,iOS實(shí)現(xiàn)QQ拖動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07iOS實(shí)現(xiàn)數(shù)字倍數(shù)動畫效果
在iOS開發(fā)中,制作動畫效果是最讓開發(fā)者享受的環(huán)節(jié)之一,下面這篇文章主要給大家介紹了關(guān)于iOS實(shí)現(xiàn)數(shù)字倍數(shù)動畫效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02