SLTimer.m 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. //
  2. // SLTimer.m
  3. //
  4. // Created by wsl on 2020/6/15.
  5. // Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved.
  6. //
  7. #import "SLTimer.h"
  8. @implementation SLTimer
  9. static NSMutableDictionary *timers_;
  10. dispatch_semaphore_t semaphore_;
  11. + (void)initialize
  12. {
  13. static dispatch_once_t onceToken;
  14. dispatch_once(&onceToken, ^{
  15. timers_ = [NSMutableDictionary dictionary];
  16. semaphore_ = dispatch_semaphore_create(1);
  17. });
  18. }
  19. + (NSString *)execTask:(void (^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async
  20. {
  21. if (!task || start < 0 || (interval <= 0 && repeats)) return nil;
  22. // 队列
  23. dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) : dispatch_get_main_queue();
  24. // 创建定时器
  25. dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
  26. // 设置时间
  27. dispatch_source_set_timer(timer,
  28. dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC),
  29. interval * NSEC_PER_SEC, 0);
  30. dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
  31. // 定时器的唯一标识
  32. NSString *name = [NSString stringWithFormat:@"%zd", timers_.count];
  33. // 存放到字典中
  34. timers_[name] = timer;
  35. dispatch_semaphore_signal(semaphore_);
  36. // 设置回调
  37. dispatch_source_set_event_handler(timer, ^{
  38. task();
  39. if (!repeats) { // 不重复的任务
  40. [self cancelTask:name];
  41. }
  42. });
  43. // 启动定时器
  44. dispatch_resume(timer);
  45. return name;
  46. }
  47. + (NSString *)execTask:(id)target selector:(SEL)selector start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async
  48. {
  49. if (!target || !selector) return nil;
  50. return [self execTask:^{
  51. if ([target respondsToSelector:selector]) {
  52. #pragma clang diagnostic push
  53. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  54. [target performSelector:selector];
  55. #pragma clang diagnostic pop
  56. }
  57. } start:start interval:interval repeats:repeats async:async];
  58. }
  59. + (void)cancelTask:(NSString *)taskName;
  60. {
  61. if (taskName.length == 0) return;
  62. dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
  63. dispatch_source_t timer = timers_[taskName];
  64. if (timer) {
  65. dispatch_source_cancel(timer);
  66. [timers_ removeObjectForKey:taskName];
  67. }
  68. dispatch_semaphore_signal(semaphore_);
  69. }
  70. @end