// // JKTimer.m // JKUtilDemo // // Created by Jack on 7/1/16. // Copyright © 2016 Emerys. All rights reserved. // #import "JKTimerManager.h" #define lockName(var) [NSString stringWithFormat:@"%@_canceller",var] #define timerLock(var) [[JKTimerManager sharedTimerManager].lockContainer objectForKey:lockName(var)] @interface JKTimerManager () @property (nonatomic,strong) NSMutableDictionary *timerContainer; @property (nonatomic,strong) NSMutableDictionary *lockContainer; @end @implementation JKTimerManager + (instancetype)sharedTimerManager { static JKTimerManager *manager = nil; static dispatch_once_t token; dispatch_once(&token, ^{ manager = [[JKTimerManager alloc] init]; }); return manager; } - (NSMutableDictionary *)timerContainer { if (!_timerContainer) { _timerContainer = [NSMutableDictionary dictionary]; } return _timerContainer; } - (void)scheduledDispatchTimerWithName:(NSString *)name timeInterval:(NSTimeInterval)timerInterval queue:(dispatch_queue_t)queue repeats:(BOOL)repeats action:(dispatch_block_t)action { if (name == nil) return; if (queue == nil) queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_source_t timer = [self.timerContainer objectForKey:name]; if (!timer) { timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_resume(timer); [self.timerContainer setObject:timer forKey:name]; } NSLock *timer_lock = [[NSLock alloc] init]; [self.lockContainer setObject:timer_lock forKey:lockName(name)]; dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timerInterval * NSEC_PER_SEC), timerInterval * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC); __weak typeof(self) weakSelf = self; dispatch_source_set_event_handler(timer, ^{ [timerLock(name) lock]; if (timer && action) { action(); if (!repeats) { [weakSelf cancelTimerWithName:name]; } } [timerLock(name) unlock]; }); } - (void)cancelTimerWithName:(NSString *)name { dispatch_source_t timer = [self.timerContainer objectForKey:name]; if (!timer) { return; } NSLock *timer_lock = timerLock(name); [timer_lock lock]; [self.lockContainer removeObjectForKey:lockName(name)]; [self.timerContainer removeObjectForKey:name]; dispatch_source_cancel(timer); timer = nil; [timer_lock unlock]; } - (void)cancelAllTimer { for (NSString *name in self.timerContainer.allKeys) { [self cancelTimerWithName:name]; } } @end