美文网首页Objective - C 底层
Objective - C 内存管理(二)GCD定时器

Objective - C 内存管理(二)GCD定时器

作者: 爱玩游戏的iOS菜鸟 | 来源:发表于2020-04-13 11:14 被阅读0次

    GCD定时器的使用场景

    NSTimer依赖于RunLoop,如果RunLoop的任务过于繁重,可能会导致NSTimer不准时,而GCD的定时器会更加准时

      //需要持有,定时器才会走
      @property(nonatomic,strong) dispatch_source_t timer;
      //主线程
      dispatch_queue_t queue = dispatch_get_main_queue();
      //子线程
      //dispatch_queue_t queue = dispatch_queue_create( "timeQueue", DISPATCH_QUEUE_SERIAL);
    
      dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        
      NSTimeInterval start = 5.0;//2秒后执行
      NSTimeInterval interval = 1.0;//间隔1秒执行
            
      dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(start* NSEC_PER_SEC)), interval * NSEC_PER_SEC, 0);
        
      NSLog(@"start");
      //设置回调
      //第一种方式 block
      dispatch_source_set_event_handler(timer, ^{
        NSLog(@"11111");
      });
    
      //第二种方式 传入函数
      //dispatch_source_set_event_handler_f(timer, timeAction);
    
      dispatch_resume(timer);
        
      self.timer = timer;
    
      /*
      void timeAction(void *param)
      {
          NSLog(@"11111 %@",[NSThread currentThread]);
      }
      */
    

    1.如果需要将定时器放在子线程中,则更换主队列为创建的队列即可
    2.GCD创建的对象(dispatch_queue_t 、dispatch_source_t)在ARC环境下,是不需要去销毁的

    下面尝试封装一下定时器方法:

    @interface ZQTimer : NSObject
    //闭包
    + (NSString *)execTask:(void(^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async;
    
    //target selector
    + (NSString *)execTaskWithTarget:(id)target selector:(SEL)selector start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async;
    
    + (void)cancelTask:(NSString *)task;
    
    @end
    
    //ZQTimer.m
    @implementation ZQTimer
    
    static NSMutableDictionary *timers_;
    static dispatch_semaphore_t semaphore_;
    
    + (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 || (repeats && interval <= 0)) return nil;
        
        //队列
        dispatch_queue_t queue = async ? dispatch_queue_create( "timeQueue", DISPATCH_QUEUE_SERIAL) : dispatch_get_main_queue();
        
        //创建定时器
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        //设置时间
        dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(start* NSEC_PER_SEC)), interval * NSEC_PER_SEC, 0);
    
        //对下面对字典的操作进行加锁
        dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
    
        //定时器的唯一标识
        NSString *name = [NSString stringWithFormat:@"%ld",timers_.count];
        
        //存放到字典中
        timers_[name] = timer;
        
        dispatch_semaphore_signal(semaphore_);
    
        //设置回调
        dispatch_source_set_event_handler(timer, ^{
            task();
            if (!repeats) {//不重复的任务
                [self cancelTask:name];
            }
        });
        
        //启动定时器
        dispatch_resume(timer);
    
        return  name;
    }
    
    + (NSString *)execTaskWithTarget:(id)target selector:(SEL)selector start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async{
        
        if (!target || !selector) return nil;
        
        return [self execTask:^{
            if ([target respondsToSelector:selector]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                [target performSelector:selector];
    #pragma clang diagnostic pop
            }
            
        } start:start interval:interval repeats:repeats async:async];
    }
    
    + (void)cancelTask:(NSString *)task{
        if (task.length == 0) return;
        
        dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
        
        dispatch_source_t timer = timers_[task];
        
        if (!timer) return;
        
        dispatch_source_cancel(timers_[task]);
        [timers_ removeObjectForKey:@"name"];
        
        dispatch_semaphore_signal(semaphore_);
    }
    
    @end
    

    调用代码:

    [ZQTimer execTask:^{
            NSLog(@"111 %@",[NSThread currentThread]);
        } start:2.0 interval:1.0 repeats:YES async:YES];
    

    相关文章

      网友评论

        本文标题:Objective - C 内存管理(二)GCD定时器

        本文链接:https://www.haomeiwen.com/subject/dnhpmhtx.html