一碌识、NSTimer定時器不準(zhǔn):
如果在子線程中創(chuàng)建Timer,那么當(dāng)我們add到RunLoop的時候有NSDefaultRunLoopMode和NSRunLoopCommonModes兩種模式可以選擇
- 這里不像主線程,子線程需要創(chuàng)建loop并且run起來痹筛,不然是不會連續(xù)跑任務(wù)的
- 不準(zhǔn)的原因在于莺治,當(dāng)我們在NSDefaultRunLoopMode模式下跑的時候,我們滾動例如TableView的時候切換到
- TrackingMode,loop會退出當(dāng)前mode帚稠,重新進入指定的mode谣旁,如果NSTimer不是加到NSRunLoopCommonModes
- 那么任務(wù)跑起來一直在切換,肯定會不準(zhǔn)
NSTimer *timer= [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
二滋早、GCD創(chuàng)建定時器
GCD創(chuàng)建的定時器不受RunLoop中Modes影響榄审;
注意
:將定時器寫成屬性,是因為內(nèi)存管理的原因杆麸,使用了dispatch_source_create方法搁进,這種方法GCD是不會幫你管理內(nèi)存的浪感。
@property (nonatomic,strong) dispatch_source_t timer;
/**
創(chuàng)建一個定時器
參數(shù)1:代表創(chuàng)建一個定時器
參數(shù)4:隊列
這里的強引用是因為,當(dāng)我定時器延時幾秒調(diào)用的時候饼问,局部變量就死了影兽,我們需要強引用起來
*/
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
/**
設(shè)置定時器
參數(shù)1:定時器對象
參數(shù)2:GCD dispatch_time_t 里面的都是納秒 創(chuàng)建一個距離現(xiàn)在多少秒開啟的任務(wù)
參數(shù)3:間隔多少秒調(diào)用一次
問題
:DISPATCH_TIME_NOW用這個,開始倒計時那1-2s會跑得有點快
dispatch_source_set_timer(self.timer,DISPATCH_TIME_NOW,1.0*NSEC_PER_SEC, 0);
*/
dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), (uint64_t)(1.0 * NSEC_PER_SEC), 0); // 設(shè)置回調(diào)
//執(zhí)行這個以后莱革,會立即執(zhí)行一次
dispatch_source_set_event_handler(self.timer, ^{
});
dispatch_resume(self.timer);
}
參數(shù)詳解:
dispatch_source_create(dispatch_source_type_t type,
uintptr_t handle,
unsigned long mask,
dispatch_queue_t _Nullable queue)
第一個參數(shù):dispatch_source_type_t type為設(shè)置GCD源方法的類型峻堰,前面已經(jīng)列舉過了。
第二個參數(shù):uintptr_t handle Apple的API介紹說盅视,暫時沒有使用捐名,傳0即可。
第三個參數(shù):unsigned long mask Apple的API介紹說闹击,使用DISPATCH_TIMER_STRICT镶蹋,會引起電量消耗加劇,畢竟要求精確時間拇砰,所以一般傳0即可梅忌,視業(yè)務(wù)情況而定。
第四個參數(shù):dispatch_queue_t _Nullable queue 隊列除破,將定時器事件處理的Block提交到哪個隊列之上牧氮。可以傳Null瑰枫,默認為全局隊列踱葛。
dispatch_source_set_timer(dispatch_source_t source,
dispatch_time_t start,
uint64_t interval,
uint64_t leeway);
第一個參數(shù):dispatch_source_t source......不用說了
第二個參數(shù):dispatch_time_t start, 定時器開始時間,類型為 dispatch_time_t光坝,其API的abstract標(biāo)明可參照dispatch_time()
和dispatch_walltime()
尸诽,同為設(shè)置時間,但是后者為“鐘表”
時間盯另,相對比較準(zhǔn)確性含,所以選擇使用后者。dispatch_walltime(const struct timespec *_Nullable when, int64_t delta),參數(shù)when可以為Null鸳惯,默認為獲取當(dāng)前時間商蕴,參數(shù)delta為增量,即獲取當(dāng)前時間的基礎(chǔ)上芝发,增加X秒的時間為開始計時時間绪商,此處傳0即可。
第三個參數(shù):uint64_t interval辅鲸,定時器間隔時長格郁,由業(yè)務(wù)需求而定。
第四個參數(shù):uint64_t leeway, 允許誤差例书,此處傳0即可锣尉。