1.GCD形式
/*ViewController為你當(dāng)前視圖控制器類名**/
__block ViewController ?*weakSelf =self;
/*
*DISPATCH_TIME_NOW:表示從現(xiàn)在開始
*3.0*NSEC_PER_SEC:表示3秒后執(zhí)行(NSEC_PER_SEC,每秒有多少納秒)
**/
dispatch_time_t delayTime =dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0*NSEC_PER_SEC));
dispatch_after(delayTime,dispatch_get_main_queue(), ^{
? ? ? ? ? [weakSelf test];
});
注:
/*
*NSEC_PER_SEC疗疟,每秒有多少納秒瑟蜈。
*USEC_PER_SEC,每秒有多少毫秒。(注意是指在納秒的基礎(chǔ)上)
*NSEC_PER_USEC斋攀,每毫秒有多少納秒捐下。
1 * NSEC_PER_SEC 等價(jià)于? 1000 * USEC_PER_SEC? 或? USEC_PER_SEC * NSEC_PER_USEC(每秒的毫秒數(shù)乘以每毫秒的納秒數(shù),也就是每秒的納秒數(shù))
**/
USEC_PER_SEC朵逝,每秒有多少毫秒蔚袍。(注意是指在納秒的基礎(chǔ)上)
NSEC_PER_USEC,每毫秒有多少納秒配名。
2.sleep形式
建議不要采用此種形式啤咽,此種方法是通過阻塞線程的方式執(zhí)行,如果要采用此種方法建議放在子線程中渠脉,否則會(huì)卡住UI界面的執(zhí)行宇整,本人受害過。
sleep(3);//程序停止三秒
//需要執(zhí)行的方法
[self test];
3.定時(shí)器形式(NSTimer)
/*
*userInfo:需要傳遞的數(shù)據(jù)芋膘,可通過NSTimer實(shí)例獲得鳞青,[timer userInfo]霸饲;返回參數(shù)為id類型,強(qiáng)轉(zhuǎn)(NSString*)一下就可以了
repeats:是指定是否循環(huán)執(zhí)行臂拓,YES將循環(huán)厚脉,NO將只執(zhí)行一次
*/
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(test) userInfo:nil repeats:NO];
//第二種創(chuàng)建方法
NSTimer* timer = [NSTimer timerWithTimeInterval:1target:self selector:@selector(test) userInfo: nil ?repeats: NO];
[[NSRunLoopcurrentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
特別注意:使用完之后要記得調(diào)用- (void)invalidate;//停止并刪除
if ( [timer isValid] ?== YES) {
? ? ? ? ? [timer invalidate];
? ? ? ? ? timer=nil;
}//在invalidate之前最好先用isValid先判斷是否還在線程中
注:1. NSTimer與RunLoop有關(guān)(其實(shí)RunLoop與線程是緊密相關(guān)的),RunLoop只能運(yùn)行在一種mode下埃儿,如果要換mode器仗,當(dāng)前的loop也需要停下重啟成新的。利用這個(gè)機(jī)制童番,ScrollView滾動(dòng)過程中NSDefaultRunLoopMode (kCFRunLoopDefaultMode)的mode會(huì)切換到UITrackingRunLoopMode來保證ScrollView的流暢滑動(dòng)精钮;只有在NSDefaultRunLoopMode模式下處理的事件會(huì)影響scrllView的滑動(dòng)。如果我們把一個(gè)NSTimer對(duì)象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運(yùn)行循環(huán)中的時(shí)候, ScrollView滾動(dòng)過程中會(huì)因?yàn)閙ode的切換剃斧,而導(dǎo)致NSTimer將不再被調(diào)度轨香。但是因?yàn)閙ode還是可定制的,所以:Timer計(jì)時(shí)會(huì)被scrollView的滑動(dòng)影響的問題可以通過將timer添加到NSRunLoopCommonModes (kCFRunLoopCommonModes) 來解決幼东。
? ? ? ?2. 需要手動(dòng)添加到RunLoop臂容, 如果不用 addTimer: forMode方法手動(dòng)加入主循環(huán)池中,將不會(huì)循環(huán)執(zhí)行根蟹。并且如果不手動(dòng)調(diào)用fair脓杉,則定時(shí)器不會(huì)啟動(dòng)。
4. performSelector形式
/*
*withObject:需要攜帶的數(shù)據(jù)简逮,不傳則寫nil
afterDelay:幾秒后執(zhí)行
**/
[self performSelector:@selector(test) withObject:nil afterDelay:3];
注:我們知道只有主線程會(huì)在創(chuàng)建的時(shí)候默認(rèn)自動(dòng)運(yùn)行一個(gè)runloop球散,并且有timer,普通的子線程是沒有這些的散庶。這樣就帶來一個(gè)問題了蕉堰,有些時(shí)候我們并不確定我們的模塊是不是會(huì)異步調(diào)用到,而我們?cè)趯戇@樣的延時(shí)調(diào)用的時(shí)候一般都不會(huì)去檢查運(yùn)行時(shí)的環(huán)境悲龟,這樣在子線程中被調(diào)用的時(shí)候屋讶,我們的代碼中的延時(shí)調(diào)用的代碼就會(huì)一直等待timer的調(diào)度,但是實(shí)際上在子線程中又沒有這樣的timer须教,這樣我們的代碼就永遠(yuǎn)不會(huì)被調(diào)到皿渗。
解決辦法:[self performSelector:@selector(test) onThread:[NSThreadmainThread] withObject:nil waitUntilDone: NO];//指定了該selector在主線程中運(yùn)行
或
[self performSelector:@selector(testDelay) withObject:nil afterDelay:3 inModes:[NSArray arrayWithObject: NSDefaultRunLoopMode]];
[[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
//啟動(dòng)線程中runloop,因?yàn)槊總€(gè)線程就有個(gè)默認(rèn)的runloop
? ? ? ? ? ?在有多線程操作的環(huán)境中轻腺,這樣performSelector的延時(shí)調(diào)用乐疆,其實(shí)是缺乏安全性的。我們可以用另一套方案來解決這個(gè)問題约计,就是使用GCD中的dispatch_after來實(shí)現(xiàn)單次的延時(shí)調(diào)用诀拭。