作用
在指定的時間執行指定的任務。
每隔一段時間執行指定的任務。
當定時器建立完(不用 scheduled 的,添加到 runloop 中)後,該定時器将在初始化時指定的 ti 秒後自動觸發。如果 NSTimer 的觸發時間到的時候,runloop 在阻塞狀态,觸發時間就會推遲到下一個 runloop 周期。
1、scheduled 方式
建立并啟動定時器。
預設将時鐘以 NSDefaultRunLoopMode 模式添加到運作循環。
發生使用者互動的時候,時鐘會被暫停。
2、timer 方式
建立定時器,添加到運作循環後啟動定時器。
将時鐘以指定的模式添加到運作循環。
1、CADisplayLink
CADisplayLink 是一個能讓我們以和螢幕重新整理率相同的頻率将内容畫到螢幕上的定時器。我們在應用中建立一個新的 CADisplayLink 對象,把它添加到一個 runloop 中,并給它提供一個 target 和 selector 在螢幕重新整理的時候調用。
一但 CADisplayLink 以特定的模式注冊到 runloop 之後,每當螢幕需要重新整理的時候,runloop 就會調用 CADisplayLink 綁定的 target 上的 selector,這時 target 可以讀到 CADisplayLink 的每次調用的時間戳,用來準備下一幀顯示需要的資料。例如一個視訊應用使用時間戳來計算下一幀要顯示的視訊資料。在 UI 做動畫的過程中,需要通過時間戳來計算 UI 對象在動畫的下一幀要更新的大小等等。
在添加進 runloop 的時候我們應該選用高一些的優先級,來保證動畫的平滑。可以設想一下,我們在動畫的過程中,runloop 被添加進來了一個高優先級的任務,那麼,下一次的調用就會被暫停轉而先去執行高優先級的任務,然後在接着執行 CADisplayLink 的調用,進而造成動畫過程的卡頓,使動畫不流暢。
另外 CADisplayLink 不能被繼承。
屬性:
2、CADisplayLink 與 NSTimer 有什麼不同
iOS 裝置的螢幕重新整理頻率是固定的,CADisplayLink 在正常情況下會在每次重新整理結束都被調用,精确度相當高。
NSTimer 的精确度就顯得低了點,比如 NSTimer 的觸發時間到的時候,runloop 如果在阻塞狀态,觸發時間就會推遲到下一個 runloop 周期。并且 NSTimer 新增了 tolerance 屬性,讓使用者可以設定可以容忍的觸發的時間的延遲範圍。
CADisplayLink 使用場合相對專一,适合做 UI 的不停重繪,比如自定義動畫引擎或者視訊播放的渲染。NSTimer 的使用範圍要廣泛的多,各種需要單次或者循環定時處理的任務都可以使用。在 UI 相關的動畫或者顯示内容使用 CADisplayLink 比起用 NSTimer 的好處就是我們不需要再格外關心螢幕的重新整理頻率了,因為它本身就是跟螢幕重新整理同步的。
3、CADisplayLink 使用示例
4、給非 UI 對象添加動畫效果
我們知道動畫效果就是一個屬性的線性變化,比如 UIView 動畫的 EasyIn EasyOut 。通過數值按照不同速率的變化我們能生成更接近真實世界的動畫效果。我們也可以利用這個特性來使一些其他屬性按照我們期望的曲線變化。比如當播放視訊時關掉視訊的聲音我可以通過 CADisplayLink 來實作一個 EasyOut 的漸出效果:先快速的降低音量,在慢慢的漸變到靜音。
5、注意
通常來講:iOS 裝置的重新整理頻率事 60HZ 也就是每秒 60 次。那麼每一次重新整理的時間就是 1/60 秒 大概 16.7 毫秒。當我們的 frameInterval 值為 1 的時候我們需要保證的是 CADisplayLink 調用的 target 的函數計算時間不應該大于 16.7 否則就會出現嚴重的丢幀現象。
在 Mac 應用中我們使用的不是 CADisplayLink 而是 CVDisplayLink 它是基于 C 接口的用起來配置有些麻煩但是用起來還是很簡單的。
<a href="http://developer.apple.com/library/ios/samplecode/AVBasicVideoOutput/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013109">Apple 官方的 Demo</a>
<a href="https://developer.apple.com/library/ios/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html">CADisplayLink Clas Reference</a>
<a href="https://github.com/zipme/RQShineLabel">一個類似 Secret 文字漸變效果的開源庫</a>
在子線程建立定時器時,需要手動開啟子線程的運作循環。
1)performSelector
2)GCD
3)NSTimer