GCD timer

推薦使用GCD方式創(chuàng)建timer的原因赦拘,GCD是基于內(nèi)核的,會更加準(zhǔn)時,NSTimer和CADisplayLink依賴于RunLoop,如果Runloop的任務(wù)太繁重逾冬,可能會導(dǎo)致NSTimer不準(zhǔn)時

GCD的Timer創(chuàng)建

//stong修飾,強(qiáng)引用
@property (nonatomic,strong) dispatch_source_t timer;

  • (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"begin");
    // Do any additional setup after loading the view.
    // 隊列
    // dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    // dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t queue = dispatch_get_main_queue();
    // 創(chuàng)建定時器
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    // 設(shè)置時間
    // dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    // 設(shè)置時間祥诽,帶有延時幾秒后執(zhí)行的開啟定時器的參數(shù)
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 2NSEC_PER_SEC), 1NSEC_PER_SEC, 0);
    // 設(shè)置回調(diào)
    dispatch_source_set_event_handler(timer, ^{
    // 上面設(shè)置為什么隊列譬圣,這個回調(diào)就在什么隊列里面執(zhí)行
    NSLog(@"執(zhí)行定時器");
    NSLog(@"%@",[NSThread currentThread]);
    });
    // 啟動定時器
    dispatch_resume(timer);
    // 設(shè)置timer為強(qiáng)引用的,否則不會執(zhí)行雄坪,出了函數(shù)調(diào)用棧厘熟,就銷毀了
    self.timer = timer;
    }
    封裝一個timer對象

.h

@interface JGTimer : NSObject
//開始定時器的方法
+(NSString *)execTask:(void(^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async;
//取消定時器
+(void)cancleTask:(NSString *)name;
@end
.m

import "JGTimer.h"

@implementation JGTimer

//使用字典來表示,任務(wù)的名字和timer一一對應(yīng)的關(guān)系,設(shè)置一個全局的字典
static NSMutableDictionary * timers_;
//使用信號量來解決多線程绳姨,同時操作字典的情況
dispatch_semaphore_t semaphore_ ;

// 使用initialize和單例初始化字典登澜,因?yàn)橹挥薪o這個類發(fā)送消息時候來回調(diào)用這個方法
+(void)initialize{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
timers_ = [NSMutableDictionary dictionary];
semaphore_ = dispatch_semaphore_create(1);
});
}
+(NSString *)execTask:(void(^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async{
if (!task || start < 0 || (interval <= 0 && repeats)) {
return nil;
}
__weak typeof(self) weakSelf = self;

dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) : dispatch_get_main_queue();

// 創(chuàng)建定時器
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 設(shè)置時間
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0);
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
// 設(shè)置任務(wù)的名字
NSString * name = [NSString stringWithFormat:@"%lu",(unsigned long)timers_.count];
// 給定時器增加強(qiáng)引用,并且是任務(wù)的名字和定時器一一對應(yīng)
timers_[name] = timer;
dispatch_semaphore_signal(semaphore_);
// 設(shè)置回調(diào)
dispatch_source_set_event_handler(timer, ^{
task();
// 如果取消這個任務(wù)飘庄,執(zhí)行一次就取消
if (!repeats) {
[weakSelf cancleTask:name];
}
});
// 啟動
dispatch_resume(timer);
return name;
}
+(void)cancleTask:(NSString *)name{
if (name.length == 0) {
return;
}
dispatch_source_t timer = timers_[name];
if (!timer) return;
// 如果信號的值為1的話脑蠕,會自動減1,然后執(zhí)行下面的代碼跪削,如果這個值為0谴仙,就會休眠等待,直到這個值大于0時候碾盐,才會喚醒和繼續(xù)執(zhí)行
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
// 取消定時器
dispatch_source_cancel(timers_[name]);
// 從字典中刪除這個定時器晃跺,刪除強(qiáng)引用
[timers_ removeObjectForKey:name];
// 信號的值+1操作
dispatch_semaphore_signal(semaphore_);
}
使用封裝的定時器

  • (void)viewDidLoad {
    [super viewDidLoad];
    /*
    NSLog(@"begin");
    // 隊列
    // dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    // dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t queue = dispatch_get_main_queue();
    // 創(chuàng)建定時器
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    // 設(shè)置時間
    // dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    // 設(shè)置時間,帶有延時幾秒后執(zhí)行的開啟定時器的參數(shù)
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 2NSEC_PER_SEC), 1NSEC_PER_SEC, 0);
    // 設(shè)置回調(diào)
    dispatch_source_set_event_handler(timer, ^{
    // 上面設(shè)置為什么隊列廓旬,這個回調(diào)就在什么隊列里面執(zhí)行
    NSLog(@"執(zhí)行定時器");
    NSLog(@"%@",[NSThread currentThread]);
    });
    // 啟動定時器
    dispatch_resume(timer);
    // 設(shè)置timer為強(qiáng)引用的哼审,否則不會執(zhí)行,出了函數(shù)調(diào)用棧孕豹,就銷毀了
    self.timer = timer;

    */

// 封裝timer
NSLog(@"begin");
self.task = [JGTimer execTask:^{
NSLog(@"111");
} start:2 interval:1 repeats:YES async:YES];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 取消定時器
[JGTimer cancleTask:self.task];
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涩盾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子励背,更是在濱河造成了極大的恐慌春霍,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叶眉,死亡現(xiàn)場離奇詭異址儒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)衅疙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門莲趣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饱溢,你說我怎么就攤上這事喧伞。” “怎么了绩郎?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵潘鲫,是天一觀的道長。 經(jīng)常有香客問我肋杖,道長溉仑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任状植,我火速辦了婚禮浊竟,結(jié)果婚禮上怨喘,老公的妹妹穿的比我還像新娘。我一直安慰自己逐沙,他們只是感情好哲思,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吩案,像睡著了一般棚赔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上徘郭,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天靠益,我揣著相機(jī)與錄音,去河邊找鬼残揉。 笑死胧后,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抱环。 我是一名探鬼主播壳快,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼镇草!你這毒婦竟也來了眶痰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤梯啤,失蹤者是張志新(化名)和其女友劉穎竖伯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體因宇,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡七婴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了察滑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片打厘。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贺辰,靈堂內(nèi)的尸體忽然破棺而出户盯,到底是詐尸還是另有隱情,我是刑警寧澤魂爪,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布先舷,位于F島的核電站艰管,受9級特大地震影響滓侍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜牲芋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一撩笆、第九天 我趴在偏房一處隱蔽的房頂上張望捺球。 院中可真熱鬧,春花似錦夕冲、人聲如沸氮兵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泣栈。三九已至,卻和暖如春弥姻,著一層夾襖步出監(jiān)牢的瞬間南片,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工庭敦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疼进,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓秧廉,卻偏偏與公主長得像伞广,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疼电,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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