麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 系統 > iOS > 正文

iOS之UITableView計時器的實現方式總結(NSTimer、DispatchSource、CADisplayLink)

2019-10-21 18:39:12
字體:
來源:轉載
供稿:網友

前言

最近工作比較忙,但是還是出來更新博客了。今天博客中所涉及的內容并不復雜,都是一些平時常見的一些問題,通過這篇博客算是對UITableView中使用定時器的幾種方式進行總結。本篇博客會給出在TableView中使用NSTimer或者DispatchSourcer中常見的五種方式。當然下方第一種方式是常規做法,不過也是UITableView中使用NSTimer的一個坑。其他三種方式是為了繞過這個坑的解決方案。

當然,本篇博客共涉及到了UITableView中使用定時器的四種實現方式,當然應該也還有其他實現方式,只不過目前我沒有涉及到。歡迎在評論區提供其他實現方式,我會及時的整合到目前的Demo中。

接下來我們先來總結一下本篇博客所涉及的四種方式:

  • 第一種就是直接在TableView的Cell上使用NSTimer,當然這種方式是有問題的,稍后會介紹。
  • 第二種是將NSTimer添加到當前線程所對應的RunLoop中的commonModes中。
  • 第三種是通過Dispatch中的TimerSource來實現定時器。
  • 第四種是開啟一個新的子線程,將NSTimer添加到這個子線程中的RunLoop中,并使用DefaultRunLoopModes來執行。
  • 第五種方式就是使用CADisplayLink來實現。

下方我們將會根據具體的示例來詳細的介紹以上這五種實現方式。

一、在Cell中直接使用NSTimer

首先我們按照常規做法,直接在UITableView的Cell上添加相應的NSTimer, 并使用scheduledTimer執行相應的代碼塊。這種方式沒有什么特殊的就是對Timer的直接使用。下方是我們本部分的Timer的使用代碼,當然是使用Swift來實現的,不過與OC的代碼差不多。代碼如下所示 :

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

上述代碼比較簡單,就是在Cell上添加了一個定時器,然后沒1秒更新一次時間,并在Cell的timeLabel上顯示,運行效果如下所示。從該運行效果中我們不難發現,當我們滑動TableView時,該定時器就停止了工作。具體原因就是當前線程的RunLoop在TableView滑動時將DefaultMode切換到了TrackingRunLoopMode。因為Timer默認是添加在RunLoop上的DefaultMode上的,當Mode切換后Timer就停止了運行。

但是當停止滑動后,Mode又切換了回來,所以Timer有可以正常工作了。

  iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

為了進一步看一下Mode的切換,我們可以在相應的地方獲取當前線程的RunLoop并且打印對應的Mode。下方代碼就是在TableView所對應的VC上添加的,我們在viewDidLoad()、viewDidAppear()以及scrollViewDidScroll()這個代理方法中對當前線程所對應的RunLoop下的currentMode進行了打印,其代碼如下。

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

下方就是最終的運行結果。從輸出結果中我們不難看出,在viewDidLoad()方法中打印的Current Mode為UIInitializationRunLoopMode, 從該Mode的名字中我們不難發現,該Mode負責UI的初始化。在viewDidApperar()方法中,也就是UI顯示后,RunLoop的Mode切換成了kCFRunLoopDefaultMode。緊接著,我們去滑動TableView,然后在scrollViewDidScroll()代理方法中打印滑動時當前RunLoop所對應的Mode。從下方運行結果不難看出,當TableView滑動時,打印出的currentModel為UITrackingRunLoopMode。當停止滑動后,點擊Show Current Mode按鈕獲取當前Mode時,打印的有時RunLoopDefaultMode。具體如下所示:

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

二、將Timer添加到CommonMode中

上一部分的定時器是不能正常運行的,因為NSTimer對象默認添加到了當前RunLoop的DefaultMode中,而在切換成TrackingRunLoopMode時,定時器就停止了工作。解決該問題最直接方法是,將NSTimer在TrackingRunLoopMode中也添加一份。這樣的話無論是在DefaultMode還是TrackingRunLoopMode中,定時器都會正常的工作。

如果你對RunLoop比較熟悉的話,可以知道CommonModes就是DefaultMode和TrackingRunLoopMode的集合,所以我們只需要將NSTimer對象與當前線程所對應的RunLoop中的CommonModes關聯即可,具體代碼如下所示:

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

上述代碼與第一部分的代碼不同的地方在于我們將創建好的定時器添加到了當前RunLoop中的CommonModes中,這樣的話可以保證TableView在滑動時定時器也可以正常運行。上述代碼最終的運行效果如下所示。

  iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

從該運行效果我們不難發現,當該TableView滾動式,其Cell上的定時器是可以正常工作的。但是當我們滑動右上角的這個TableView時,第一個的TableView中的定時器也是不能正常工作的,因為這些TableView都在主線程中工作,也就是說這些TableView所在的RunLoop是同一個。

三、將Timer添加到子線程的RunLoop下的DefaultMode中

接下來我們來看另一種解決方案,就是開啟一個新的子線程,然后將Timer添加到這個子線程所對應的RunLoop中。當然因為是子線程的RunLoop,在添加Timer時,我們可以將Timer添加到子線程中的RunLoop中的DefaultMode中。添加完畢后,手動運行該RunLoop。

因為是在子線程中添加的Timer, Timer肯定是在子線程中工作的,所以在更新UI時,我們需要在主線程中進行更新,具體代碼如下所示:

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

在上述代碼中我們可以看到我們使用全局的并行隊列來異步創建了一個Timer對象,然后將該對象添加進了該異步線程中的DefaultRunLoopMode中,然后運行該RunLoop。當然在子線程中更新UI還是需要在主線程中去操作的。下方就是上述代碼的運行效果。從該效果中我們不難看出,當滑動TableView時定時器是可以正常工作的。

  iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

四、DispatchTimerSource

接下來我們就不使用NSTimer來實現定時器了。在之前的博客中聊GCD時其中用到了DispatchTimerSource來實現定時器。接下來我們就在TableView的Cell上添加DispatchTimerSource,然后看一下運行效果。當然下方代碼片段我們是在全局隊列中添加的DispatchTimerSource,在主線程中進行更新。當然我們也可以在mainQueue中添加DispatchTimerSource,這樣也是可以正常工作的。當然我們不建議在MainQueue中做,因為在編程時盡量的把一些和主線程關聯不太大的操作放到子線程中去做。代碼如下所示:

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

接下來我們來看一下上述的代碼的運行效果,從該效果中我們可以看出該定時器是可以正常工作的。

  iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

五、CADisplayLink

接下來我們來使用CADisplayLink來實現定時器功能,在之前的博客中我們也使用過CADisplayLink,不過是用來計算FPS的。下方代碼片段中我們就使用CADisplayLink來實現的定時器。CADisplayLink可以添加到RunLoop中,RunLoop的每一次循環都會觸發CADisplayLink所關聯的方法。在屏幕不卡頓的情況下,每次循環的時間時1/60秒。

下方代碼,為了不讓屏幕的卡頓等引起的主線程所對應的RunLoop阻塞所造成的定時器不精確的問題。我們開啟了一個新的線程,并且將CADisplayLink對象添加到這個子線程的RunLoop中,然后在主線程中更新UI即可。具體代碼如下:

iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

我們對上述代碼運行,下方是其對應的運行結果。從下方運行結果中我們不難看出,在TableView滾動時該定時器也是可以正常運行的。當然該方式實現的定時器的精度是比較高的。

  iOS,UITableView,計時器,NSTimer,DispatchSource,CADisplayLink

經過上述五大部分,我們羅列了定時器的幾種實現方式,通過對比我們不難發現其優劣性。上述定時器中DispatchSourceTime以及CADisplayLink的精度要比NSTimer的精度要高。從代碼實現中我們不難看出CADisplayLink的精度是比較高的。

本篇博客所涉及代碼的github分享地址為:https://github.com/lizelu/NSTimerWithRunLoop

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产精品99久久久久久久vr | 国产一国产一级毛片视频 | 欧美视频一级 | 久久av喷吹av高潮av懂色 | 成年人黄视频 | 91久久国产露脸精品国产 | 国产超碰人人做人人爱 | 黄色毛片免费看 | 精品久久久久久久久中文字幕 | 久久国产精品区 | 欧美激情综合在线 | 爱福利视频 | 黄色一级片免费观看 | 精品亚洲夜色av98在线观看 | 精品一区二区免费视频视频 | 久久久久久久久久亚洲 | 黄色片免费看看 | 国产精品爆操 | 成人一级视频在线观看 | 91亚洲免费视频 | 亚洲91精品 | 九九热这里只有精品8 | 免费看a级片 | 第四色成人网 | 欧美黄色一级片在线观看 | 黄色大片在线免费观看 | 亚洲五码在线观看视频 | 久久恋| 亚洲午夜影院在线观看 | 国产精品美女一区二区 | 狠狠操视频网站 | 一区二区网 | 免费黄色入口 | 欧美18—19sex性护士中国 | 黄色网址免费入口 | 高清一区二区在线观看 | 黄色片网站在线免费观看 | 国产成人午夜高潮毛片 | 最新中文字幕在线 | 精品久久久久久久久亚洲 | 日韩电影一区二区三区 |