IOS定時(shí)器延時(shí)的探究

在日常開發(fā)中,我們經(jīng)常要延時(shí)等待(如網(wǎng)絡(luò)請(qǐng)求素邪,UI更新完)然后做一些事情揭朝,或者是做一些周期性的處理。這個(gè)時(shí)候就要求我們實(shí)現(xiàn)一個(gè)周期性的定時(shí)器進(jìn)行延時(shí)操作欣除。常用的延時(shí)實(shí)現(xiàn)方法有下面三種:

1.NStimer實(shí)現(xiàn)

不管是一次性的還是周期性的timer的實(shí)際觸發(fā)事件的時(shí)間住拭,都會(huì)與所加入的RunLoop和RunLoop Mode有關(guān),如果此RunLoop正在執(zhí)行一個(gè)連續(xù)性的運(yùn)算历帚,timer就會(huì)被延時(shí)觸發(fā)滔岳。重復(fù)性的timer遇到這種情況,如果延遲超過了一個(gè)周期挽牢,則會(huì)在延時(shí)結(jié)束后立刻執(zhí)行谱煤,并按照之前指定的周期繼續(xù)執(zhí)行。(PS: 所以有時(shí)使用timer禽拔,會(huì)偶爾出現(xiàn)連續(xù)兩次刷新的情況刘离,可能上一次timer被阻塞)

NSTimer *timer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(changeUI) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

上面方式:每隔一秒調(diào)用一次定時(shí)器的block

使用注意:1. 這個(gè)runLoop運(yùn)行模式,建議使用NSRunLoopCommonModes睹栖;使用NSDefaultRunLoopMode硫惕,在屏幕上有UI更新(如ScrollView滑動(dòng)時(shí)),runLoop就會(huì)被切換到其他的模式(NSEventTrackingRunLoopMode)野来,此時(shí)timer不會(huì)被執(zhí)行恼除。NSRunLoopCommonModes中包含了NSEventTrackingRunLoopMode,timer照樣被執(zhí)行

2.當(dāng)不在使用這個(gè)timer時(shí)曼氛,需要手動(dòng)調(diào)用invalidate方法將timer釋放并重置為nil豁辉。因?yàn)樵趧?chuàng)建timer時(shí),會(huì)默認(rèn)對(duì)target進(jìn)行一次retain搪锣,如果不手動(dòng)釋放timer秋忙,target對(duì)象也得不到釋放會(huì)造成內(nèi)存泄露

3.主線程開啟,回調(diào)的selector默認(rèn)也在主線程執(zhí)行构舟。如果想要多線程執(zhí)行timer灰追,需要手動(dòng)開啟一個(gè)NSthread,值得主要的是:由于子線程的runLoop默認(rèn)是關(guān)閉的狗超,所以需要手動(dòng)開啟子線程的runLoop弹澎,否則timer永遠(yuǎn)不會(huì)被執(zhí)行

//創(chuàng)建并執(zhí)行新的線程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];

[thread start];

//在新線程開啟定時(shí)器

- (void)openTimer

@autoreleasepool

{

//在當(dāng)前Run Loop中添加timer,模式是默認(rèn)的NSDefaultRunLoopMode

[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES];

//開始執(zhí)行新線程的Run Loop

[[NSRunLoop currentRunLoop] run];

}

}

2.CADisplayLink:

frameInterval :NSInteger類型的值努咐,用來設(shè)置間隔多少幀調(diào)用一次selector方法苦蒿,默認(rèn)值是1,即每幀都調(diào)用一次渗稍。

duration:readOnly的CFTimeInterval值佩迟,表示兩次屏幕刷新之間的時(shí)間間隔团滥。需要注意的是,該屬性在target的selector被首次調(diào)用以后才會(huì)被賦值报强。selector的調(diào)用間隔時(shí)間計(jì)算方式是:調(diào)用間隔時(shí)間 = duration * frameInterval (調(diào)用一次方法刷新幀數(shù) *刷新每一幀所需的時(shí)間)

CADisplayLink的使用跟timer比較類似灸姊,這里就不詳細(xì)介紹。朋友們可以參考參考下面這個(gè)鏈接秉溉。

http://blog.csdn.net/ch_soft/article/details/9408855

3.GCD實(shí)現(xiàn)Timer

GCD中的Timer應(yīng)該是最靈活的力惯,而且是多線程的。GCD中的Timer是靠Dispatch Source來實(shí)現(xiàn)的召嘶。

最近使用GCD的timer做一個(gè)驗(yàn)證碼發(fā)送的例子父晶。整個(gè)使用過程分為五步,代碼如下:

__block NSInteger time = 59; //倒計(jì)時(shí)時(shí)間

//1.創(chuàng)建一個(gè)全局并發(fā)隊(duì)列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//2.創(chuàng)建一個(gè)timer加到隊(duì)列中

dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

//3.設(shè)置timer的執(zhí)行周期弄跌,最后一個(gè)參數(shù)表示延時(shí)秒數(shù)為0甲喝,盡可能精確

dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0);

//4.設(shè)置timer周期執(zhí)行的block

dispatch_source_set_event_handler(_timer, ^{

if(time <= 0){ //倒計(jì)時(shí)結(jié)束,關(guān)閉定時(shí)器碟绑,還原UI

dispatch_source_cancel(_timer);

dispatch_async(dispatch_get_main_queue(), ^{

//設(shè)置按鈕的樣式

[self.getMsgBtn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];

[self.getMsgBtn setTitleColor:ZGColor(25, 111, 255) forState:UIControlStateNormal];

[self.getMsgBtn setBackgroundColor:[UIColor whiteColor]];

self.getMsgBtn.titleLabel.font = [UIFont systemFontOfSize: 14.0];

self.getMsgBtn.userInteractionEnabled = YES;

});

}else{ //否則繼續(xù)計(jì)時(shí)

int leftSeconds = time % 60;

dispatch_async(dispatch_get_main_queue(), ^{

//設(shè)置按鈕顯示讀秒效果

[self.getMsgBtn setTitle:[NSString stringWithFormat:@"%d秒后重新發(fā)送",leftSeconds] forState:UIControlStateNormal];

[self.getMsgBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

[self.getMsgBtn setBackgroundColor:[UIColor lightGrayColor]];

self.getMsgBtn.titleLabel.font = [UIFont systemFontOfSize: 13.0];

self.getMsgBtn.userInteractionEnabled = NO;

});

time--;

}

});

//5.啟動(dòng)timer

dispatch_resume(_timer);

使用注意:由于dispatch_source_t 創(chuàng)建后默認(rèn)是暫停狀態(tài)俺猿,需要手動(dòng)開啟才會(huì)執(zhí)行茎匠。

另外格仲,實(shí)際開發(fā)中有需求:等待reload執(zhí)行完刷新完tableView,然后做一些操作

想要程序延遲到reloadData結(jié)束在操作诵冒,可以用以下方法

方法1:

[self.tableView reloadData];

[self.tableView layoutIfNeeded];

//刷新完成

…….

layoutIfNeeded會(huì)強(qiáng)制重繪并等待完成凯肋。

方法2:

[objc] view plain copy

[self.tableView reloadData];

dispatch_sync(dispatch_get_main_queue(), ^{

//刷新完成

});

reloadData會(huì)在主隊(duì)列執(zhí)行,而dispatch_get_main_queue會(huì)等待機(jī)會(huì)汽馋,直到主隊(duì)列空閑才執(zhí)行侮东。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市豹芯,隨后出現(xiàn)的幾起案子悄雅,更是在濱河造成了極大的恐慌,老刑警劉巖铁蹈,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宽闲,死亡現(xiàn)場離奇詭異,居然都是意外死亡握牧,警方通過查閱死者的電腦和手機(jī)容诬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沿腰,“玉大人览徒,你說我怎么就攤上這事∷塘” “怎么了习蓬?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵纽什,是天一觀的道長。 經(jīng)常有香客問我躲叼,道長稿湿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任押赊,我火速辦了婚禮饺藤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘流礁。我一直安慰自己涕俗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布神帅。 她就那樣靜靜地躺著再姑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪找御。 梳的紋絲不亂的頭發(fā)上元镀,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音霎桅,去河邊找鬼栖疑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛滔驶,可吹牛的內(nèi)容都是我干的遇革。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼揭糕,長吁一口氣:“原來是場噩夢啊……” “哼萝快!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起著角,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤揪漩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吏口,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奄容,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锨侯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫩海。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡囚痴,死狀恐怖叁怪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情深滚,我是刑警寧澤奕谭,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布涣觉,位于F島的核電站,受9級(jí)特大地震影響血柳,放射性物質(zhì)發(fā)生泄漏官册。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一难捌、第九天 我趴在偏房一處隱蔽的房頂上張望膝宁。 院中可真熱鬧,春花似錦根吁、人聲如沸员淫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽介返。三九已至,卻和暖如春沃斤,著一層夾襖步出監(jiān)牢的瞬間圣蝎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工衡瓶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留徘公,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓鞍陨,卻偏偏與公主長得像步淹,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诚撵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 目錄(GCD): 關(guān)鍵詞 混淆點(diǎn) 場景應(yīng)用 總結(jié) 1. 關(guān)鍵詞 線程概念: 獨(dú)立執(zhí)行的代碼段,一個(gè)線程同時(shí)間只能執(zhí)...
    Ryan___閱讀 1,271評(píng)論 0 3
  • 在軟件開發(fā)過程中键闺,我們常常需要在某個(gè)時(shí)間后執(zhí)行某個(gè)方法寿烟,或者是按照某個(gè)周期一直執(zhí)行某個(gè)方法。在這個(gè)時(shí)候辛燥,我們就需要...
    誰遇而安閱讀 20,932評(píng)論 2 20
  • iOS中定時(shí)器有三種筛武,分別是NSTimer、CADisplayLink挎塌、dispatch_source徘六,下面就分別...
    HK_Hank閱讀 12,362評(píng)論 9 25
  • ======================= 前言 RunLoop 是 iOS 和 OSX 開發(fā)中非常基礎(chǔ)的一個(gè)...
    i憬銘閱讀 880評(píng)論 0 4
  • 爺爺一生寡言少語榴都,幼時(shí)經(jīng)歷抗日戰(zhàn)爭待锈,行事是十足的老一輩黨員作風(fēng),嚴(yán)謹(jǐn)克制嘴高,做的比說的多竿音,想的又比做的多和屎。 他的妻子...
    歐澈閱讀 2,781評(píng)論 51 42