在軟件開發(fā)過程中,常常會遇到在某個(gè)時(shí)間或按照某個(gè)周期來執(zhí)行一些任務(wù)鸯绿,在這個(gè)時(shí)候跋破,就會用到定時(shí)器。這里總結(jié)了 iOS 開發(fā)中經(jīng)常會用到的幾種定時(shí)器方法瓶蝴,如有不足毒返,歡迎指正。
一舷手、NSTimer
在 NSTimer 中有以下兩種方法可以實(shí)現(xiàn)定時(shí)器:
/**
TimerInterval : 執(zhí)行之前等待的時(shí)間拧簸。比如設(shè)置成 2.0,就代表 2 秒后執(zhí)行方法
target : 需要執(zhí)行方法的對象
selector : 需要執(zhí)行的方法
repeats : 是否需要循環(huán)
*/
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
- 該方法內(nèi)部默認(rèn)會把創(chuàng)建的定時(shí)器添加到當(dāng)前的 Runloop男窟,并指定運(yùn)行模式為默認(rèn) NSDefaultRunLoopMode
- 如果發(fā)生 Scrollview 的拖動(dòng)操作盆赤,Runloop 的運(yùn)行模式就會切換到 UITrackingRunLoopMode,導(dǎo)致定時(shí)器暫停工作
- 等 Runloop 的運(yùn)行模式回到 NSDefaultRunLoopMode歉眷,定時(shí)器才會恢復(fù)工作
//創(chuàng)建定時(shí)器對象
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
//添加到當(dāng)前線程的 Runloop 上牺六,并指定運(yùn)行模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
- 該方法需要手動(dòng)將創(chuàng)建的定時(shí)器添加到 Runloop 上,并指定運(yùn)行模式汗捡,使用比較靈活
- 不同運(yùn)行模式的作用:
- NSDefaultRunLoopMode:默認(rèn)狀態(tài)淑际,無 Scrollview 拖動(dòng)操作時(shí)運(yùn)行
- UITrackingRunLoopMode:有 Scrollview 拖動(dòng)操作時(shí)運(yùn)行
- NSRunLoopCommonModes:不論是否有 Scrollview 的拖動(dòng)操作,均可運(yùn)行
二扇住、CADisplayLink
//創(chuàng)建定時(shí)器對象
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(run)];
//添加到 Runloop 中春缕,并指定運(yùn)行模式
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
- 使用 CADisplayLink 時(shí),當(dāng)屏幕刷新的時(shí)候會自動(dòng)調(diào)用該定時(shí)器(每秒 60 次)台囱,可以保證我們將特定的內(nèi)容同步顯示到屏幕上淡溯,精確度比較高
- 如果 CPU 過于繁忙或者定時(shí)器任務(wù)比較耗時(shí),無法保證每秒 60 次的頻率簿训,就會自動(dòng)跳過若干次的調(diào)用咱娶,具體取決于 CPU 的忙碌程度
三米间、GCD 中的定時(shí)器
//1.創(chuàng)建定時(shí)器對象
/**
第一個(gè)參數(shù):創(chuàng)建的source的類型 DISPATCH_SOURCE_TYPE_TIMER 定時(shí)器事件
第二個(gè)參數(shù):描述信息
第三個(gè)參數(shù):更詳細(xì)的描述信息
第四個(gè)參數(shù):隊(duì)列(線程)[如果是主隊(duì)列就在主線程中執(zhí)行,否則就在子線程中執(zhí)行]
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_queue_create("GCD 的定時(shí)器", DISPATCH_QUEUE_SERIAL));
//2.設(shè)置定時(shí)器
/**
第一個(gè)參數(shù):定時(shí)器對象
第二個(gè)參數(shù):開始時(shí)間(第一次執(zhí)行時(shí)的時(shí)間)
第三個(gè)參數(shù):間隔時(shí)間(GCD的時(shí)間單位是納秒)
第四個(gè)參數(shù):精準(zhǔn)度(允許的誤差)
*/
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//3.設(shè)置定時(shí)器事件
dispatch_source_set_event_handler(timer, ^{
NSLog(@"GCD --- %@", [NSThread currentThread]);
});
//4.執(zhí)行定時(shí)器
dispatch_resume(timer);
//5.為了防止創(chuàng)建的定時(shí)器對象銷毀膘侮,需要設(shè)置一個(gè)屬性進(jìn)行強(qiáng)引用
self.timer = timer;
- GCD 中的定時(shí)器方法看似比較麻煩屈糊,其實(shí)我們可以利用 Xcode 來迅速創(chuàng)建,只需要在編輯區(qū)輸入 dispatchtimer琼了,找到如下提示即可快速創(chuàng)建逻锐,填入相應(yīng)的參數(shù)即可。
通過 Xcode 迅速創(chuàng)建 GCD 定時(shí)器
- 補(bǔ)充:以上方法在開始定時(shí)器時(shí)會直接執(zhí)行一次雕薪,如果想要開始后延時(shí)一段時(shí)間再執(zhí)行昧诱,可以修改設(shè)置定時(shí)器的方法中的開始時(shí)間,必須使用以下方法所袁,不能直接修改:
dispatch_time_t afterTime = dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC);
dispatch_source_set_timer(timer, afterTime, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
這樣就可以滿足開始定時(shí)器 2 秒之后再執(zhí)行事件盏档。