iOS中GCD定時(shí)器詳解
前言:CADisplayLink、NSTimer 不準(zhǔn)時(shí)
?CADisplayLink、NSTimer是基于RunLoop機(jī)制的,如果RunLoop的任務(wù)過(guò)于繁重,有可能會(huì)導(dǎo)致前兩個(gè)定時(shí)器不準(zhǔn)時(shí)。
舉個(gè)例子:
?加入我們創(chuàng)建了一個(gè)NSTimer定時(shí)器,每1秒鐘做任務(wù)。那么,什么時(shí)候執(zhí)行NSTimer呢?
?是在RunLoop跑圈的過(guò)程中執(zhí)行NSTimer定時(shí)器,而RunLoop跑完一圈執(zhí)行的時(shí)間不固定,也就導(dǎo)致有可能1秒鐘過(guò)去了,但是RunLoop還沒(méi)有執(zhí)行到定時(shí)器的任務(wù),那么,這就造成定時(shí)器有可能不準(zhǔn)時(shí)。
一、GCD 定時(shí)器
?GCD是不依賴(lài)與RunLoop,是直接跟系統(tǒng)內(nèi)核交互的。時(shí)間比較準(zhǔn)確。
GCD 定時(shí)器簡(jiǎn)單的使用:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"begin"); // 隊(duì)列 dispatch_queue_t queue = dispatch_get_main_queue(); // 創(chuàng)建定時(shí)器 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); // 設(shè)置時(shí)間 uint64_t start = 2.0; uint64_t interval = 1.0; dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0); // 設(shè)置回調(diào) dispatch_source_set_event_handler(timer, ^{ NSLog(@"111"); }); // 啟動(dòng)定時(shí)器 dispatch_resume(timer); self.timer = timer; }
2022-07-05 17:42:46.674345+0800 Interview02-GCD定時(shí)器[13943:350556] begin
2022-07-05 17:42:48.675440+0800 Interview02-GCD定時(shí)器[13943:350556] 111
2022-07-05 17:42:49.675542+0800 Interview02-GCD定時(shí)器[13943:350556] 111
2022-07-05 17:42:50.675350+0800 Interview02-GCD定時(shí)器[13943:350556] 111
2022-07-05 17:42:51.674523+0800 Interview02-GCD定時(shí)器[13943:350556] 111
二、GCD 定時(shí)器的實(shí)現(xiàn)方案
第一步:封裝
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface RHGCDTimer : NSObject + (NSString *)timerWithBlockTask:(void(^)(void))blockTask star:(float)star interval:(float)interval repeat:(BOOL)repeat async:(BOOL)async; + (void)cancelTask:(NSString *)name; @end NS_ASSUME_NONNULL_END
#import "RHGCDTimer.h" static NSMutableDictionary *timersDict; static dispatch_semaphore_t semaphore; @implementation RHGCDTimer + (void)initialize { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ timersDict = [NSMutableDictionary dictionary]; semaphore = dispatch_semaphore_create(1);//創(chuàng)建一個(gè)信號(hào)量,只允許一個(gè)線(xiàn)程操作 }); } + (NSString *)timerWithBlockTask:(void (^)(void))blockTask star:(float)star interval:(float)interval repeat:(BOOL)repeat async:(BOOL)async { if (!blockTask || star<0 || (repeat && interval <= 0)) return nil; //創(chuàng)建隊(duì)列,隊(duì)列決定到時(shí)候任務(wù)是在哪個(gè)線(xiàn)程執(zhí)行 dispatch_queue_t queue = async ? dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL) : dispatch_get_main_queue(); //創(chuàng)建一個(gè)定時(shí)器 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); /** dispatch_source_set_timer 上面的定時(shí)器 dispatch_time_t start 開(kāi)始時(shí)間 (typedef uint64_t dispatch_time_t;) uint64_t interval 間隔 uint64_t leeway 誤差一般寫(xiě)0 */ dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, star * NSEC_PER_SEC), interval *NSEC_PER_SEC, 0); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//信號(hào)量 //定時(shí)器唯一標(biāo)識(shí) static int i = 0; NSString *name = [NSString stringWithFormat:@"%d", i++]; //放進(jìn)字典,就會(huì)產(chǎn)生強(qiáng)引用 timersDict[name] = timer; dispatch_semaphore_signal(semaphore); //設(shè)置回調(diào) dispatch_source_set_event_handler(timer, ^{ blockTask(); if (!repeat) {//如果非重復(fù)執(zhí)行 [self cancelTask:name];//取消定時(shí)器 } }); //啟動(dòng)定時(shí)器 dispatch_resume(timer); //GCD不需要銷(xiāo)毀 return name; } + (void)cancelTask:(NSString *)name { if (name.length == 0) return; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_source_t timer = timersDict[name]; if (!timer) return; dispatch_source_cancel(timer); [timersDict removeObjectForKey:name]; dispatch_semaphore_signal(semaphore); } @end
第二步:使用
#import "ViewController.h" #import "RHGCDTimer.h" @interface ViewController () @property (copy, nonatomic) NSString *task; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.task = [RHGCDTimer timerWithBlockTask:^{ NSLog(@"執(zhí)行任務(wù)---%@", [NSThread currentThread]); } star:2.0 interval:1.0 repeat:YES async:YES]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [RHGCDTimer cancelTask:self.task]; } @end
第三步:測(cè)試驗(yàn)證
2022-07-05 17:31:41.375918+0800 Interview02-GCD定時(shí)器[13519:337316] 執(zhí)行任務(wù)---<_NSMainThread: 0x600002448880>{number = 1, name = main}
2022-07-05 17:31:42.375935+0800 Interview02-GCD定時(shí)器[13519:337316] 執(zhí)行任務(wù)---<_NSMainThread: 0x600002448880>{number = 1, name = main}
2022-07-05 17:31:43.375871+0800 Interview02-GCD定時(shí)器[13519:337316] 執(zhí)行任務(wù)---<_NSMainThread: 0x600002448880>{number = 1, name = main}
到此這篇關(guān)于iOS中GCD定時(shí)器詳解的文章就介紹到這了,更多相關(guān)iOS GCD定時(shí)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- iOS定時(shí)器的選擇CADisplayLink NSTimer和GCD使用
- iOS DispatchSourceTimer 定時(shí)器的具體使用
- iOS中幾種定時(shí)器的實(shí)現(xiàn)小結(jié)
- IOS 中NSTimer定時(shí)器的使用
- iOS中最全的各種定時(shí)器使用教程
- iOS仿小紅書(shū)呼吸燈動(dòng)畫(huà)(核心動(dòng)畫(huà)和定時(shí)器)兩種方式實(shí)現(xiàn)
- iOS開(kāi)發(fā)定時(shí)器的三種方法分享
- iOS中的NSTimer定時(shí)器的初步使用解析
- iOS中的3種定時(shí)器匯總介紹
相關(guān)文章
iOS版微信朋友圈識(shí)別圖片位置信息 如何實(shí)現(xiàn)?
這篇文章主要為大家詳細(xì)介紹了iOS版微信朋友圈識(shí)別圖片位置信息的實(shí)現(xiàn)方法2016-10-10詳解ios監(jiān)聽(tīng)reloadData刷新列表完畢的時(shí)機(jī)
這篇文章主要介紹了詳解ios監(jiān)聽(tīng)reloadData刷新列表完畢的時(shí)機(jī),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11iOS中的UISearchBar搜索框組件基礎(chǔ)使用指南
iOS開(kāi)發(fā)套件中自帶的UISearchBar搜索框我們平時(shí)經(jīng)??梢杂玫?我們可以在默認(rèn)的基礎(chǔ)上修改文字顏色、背景顏色和背景圖片等,這里我們稍微總結(jié)一下iOS中的UISearchBar搜索框組件基礎(chǔ)使用指南.2016-05-05IOS中UIImageView方法實(shí)現(xiàn)簡(jiǎn)單動(dòng)畫(huà)
這篇文章主要介紹了IOS中UIImageView方法實(shí)現(xiàn)簡(jiǎn)單動(dòng)畫(huà)的相關(guān)資料,需要的朋友可以參考下2017-05-05iOS實(shí)現(xiàn)簡(jiǎn)單長(zhǎng)截圖
這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)簡(jiǎn)單長(zhǎng)截圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07iOS開(kāi)發(fā)中UIImageView控件的常用操作整理
這篇文章主要介紹了iOS開(kāi)發(fā)中UIImageView控件的常用操作整理,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-01-01UIMenuController在Cell內(nèi)部無(wú)法顯示的解決辦法(iOS9.2)
這篇文章主要為大家詳細(xì)介紹了UIMenuController在Cell內(nèi)部無(wú)法顯示的解決辦法,感興趣的小伙伴們可以參考一下2016-08-08