1.背景介紹:NSTimer是什么鬼
這貨大家從它的『臉』估計就能知道它是啥東西了,是的,計時器。但是,如果你說NSTimer就是計時器,肯定會有人說你太業余,叫法不准確,然后以一個大牛的姿態說一些正常人聽不懂的並且帶有諷刺味道的話。呵呵,這都不重要,因為大家都是被大牛虐出來的,今后也會去虐別人。重要的是NSTimer能干什么,這才是我們關心的,至於它的定義或者概念是什么,還是交給英語系的童鞋去操心吧。所以,在介紹NSTimer的功能之前,我們還姑且就把它叫做計時器吧,它能做的就是從現在開始到后面的某一個時刻或者周期性的執行我們指定的方法的對象。
2.使用NSTimer之前要了解的知識
(1)NSTimer有以下兩個常用的方法
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
創建一個計時器,參數1:時間間隔(秒),參數2:表示發送的對象(一般填self),參數3:要執行的方法,參數4:傳遞信息(可以以字典的形式,將信息傳遞給要執行的方法),參數5:是否重復執行,如果NO,timer執行一次后便失效。
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
創建一個計時器,參數1:時間間隔(秒),參數2:表示發送的對象(一般填self),參數3:要執行的方法,參數4:傳遞信息(可以以字典的形式,將信息傳遞給要執行的方法),參數5:是否重復執行,如果NO,timer執行一次后便失效。
大家可能發現了,第一個方法和第二個方法貌似是一樣的?是的,他們基本是一樣的,但是也是有一些區別的,繼續向下看,你會知道它們的不同之處的。
(2)運行循環RunLoop
不知道大家有沒有想過這個問題,一個應用開始運行以后放在那里,如果不對它進行任何操作,這個應用就像靜止了一樣,不會自發的有任何動作發生,但是如果我們點擊界面上的一個按鈕,這個時候就會有對應的按鈕響應事件發生。給我們的感覺就像應用一直處於隨時待命的狀態,在沒人操作的時候它一直在休息,在讓它干活的時候,它就能立刻響應。其實,這就是run loop的功勞。(此段話寨子CSDN)
大家可以把運行循環理解成一個系統級的線程,它時刻在監聽着系統各種事件,一旦有事件發生,他就會觸發處於運行循環中的程序。NSTimer也一樣,只有加入運行循環中才能正常運行。但是,加入運行循環也是分好多種情況的,就像我們去上班,高富帥開車去,普通青年做地鐵去,文藝青年不去。NSTimer加入運行循環常見的有兩種模式,第一種是默認模式(NSDefaultRunLoopModel),第二種是(NSRunLoopCommonModels)。
(3)timerWithTimeInterval和scheduledTimerWithTimeInterval的區別
知道了運行循環的兩種模式,我們就能說清楚這兩個方法有什么區別了。scheduledTimerWithTimeInterval方法創建完timer之后,會自動以NSDefaultRunLoopModel模式加入運行循環。而timerWithTimeInterval方法創建的timer,不會自動加入運行循環,需要我們手動指定模式,並手動加入運行循環。
至於這兩種模式又有什么不同,接下來我們會通過代碼得到答案。
3.一些例子
例1:
以上例子說明:scheduledTimerWithTimeInterval方法創建timer后,即可加入運行循環進行執行,userinfo信息可通過參數攜帶到方法中。
例2:
同樣是上述代碼,我們在界面中加入了textView控件,在計時器執行的過程中,我們拖動textView控件,發現計時器會中斷,停止拖動textView后,計時器繼續執行。
以上代碼說明,在默認模式下(NSDefaultRunLoopModel),當有滾動事件發生,運行循環就會暫時停止NSTimer的執行,當滾動事件結束后,再繼續執行NSTimer計時器。那么,在另外一種模式(NSRunLoopCommonModels)下又會是怎樣的呢。我們一起再來看看,當然,想要使用NSRunLoopCommonModels模式,我們就要用timerWithTimeInterval方法來創建timer了。
例3:
在上述代碼中我們發現,在NSRunLoopCommonModels模式下,無論我們怎么滾動視圖,NSTimer也會正常執行的。
以上例子說明了這兩種模式表現出來的現象,其實這兩種模式的區別是:
NSDefaultRunLoopModel:監聽用戶最基本的操作(點擊,觸摸等)
NSRunLoopCommonModels:監聽一些特殊操作:滾動等
那么,為什么在NSDefaultRunLoopModel模式下發生滾動,計時器會停止呢?那是因為系統認為,用戶不應該邊滾動邊操作界面,所以停止了(觸碰,點擊等)NSDefaultRunLoopModel模式下監聽的事件。
4.使用NSTimer是不准確的計時
假設NSTimer要執行 A,B,C,D四個任務,當執行到B的時候被中斷,那么,當NStimer獲得繼續執行的權利之后,會把B,C一起執行。換句話說,NSTimer不會遺漏任務,但也無法保證按時准確執行任務。那么,ios中怎么保證准時執行任務呢?一般情況下,我們會使用CADisplayLink。它會在屏幕每次刷新時執行一次。而屏幕的刷新頻率每秒要達到幾十次,從而保證的時間的准確性。
以上內容是個人對NSTimer膚淺的認識,今后如果有進一步的了解,還會對文章進行更新。歡迎大家批評指正。
(完)