美文网首页
iOS GCD定时器封装

iOS GCD定时器封装

作者: 笔头还没烂 | 来源:发表于2022-03-27 23:04 被阅读0次

    iOS 使用定时器,大多数人都会采用GCD方案。其中一个比较重要的原因是 GCD定时器不依赖RunLoop,没有NSTimer 不准时的问题。为了方便日后使用,我封装了GCD的代码。需要的自取。
    因为废话不多说,直接上代码:
    .h文件代码如下:

    
    #import <UIKit/UIKit.h>
    
    @interface GQTimer : NSObject
    /*
     第一个参数: block,传入要执行的任务;
     第二个参数: start,传入需要什么时候开始执行,如需立马执行任务,直接传0;
     第三个参数: interval,传入时间间隔,即隔多长时间再次执行任务;
     第四个参数: repet,是否重复执行任务,如任务需重复执行,传YES;如只需执行一次,则传NO;
     第五年参数: async,是否异步执行任务,如需要主线程执行,则传NO;如需在子线程执行,则传YES
     */
    + (NSString *)createTimerWithTask:(void(^)(void))block
                     startTimer:(NSTimeInterval)start
                       interval:(NSTimeInterval)interval
                          repet:(BOOL)repet
                          async:(BOOL)async;
    /*
     第一个参数:target,传执行任务的实例对象
     第二个参数:sel,执行的任务selector
     第三个参数: start,传入需要什么时候开始执行,如需立马执行任务,直接传0;
     第四个参数: interval,传入时间间隔,即隔多长时间再次执行任务;
     第五个参数: repet,是否重复执行任务,如任务需重复执行,传YES;如只需执行一次,则传NO;
     第六年参数: async,是否异步执行任务,如需要主线程执行,则传NO;如需在子线程执行,则传YES
     */
    
    + (NSString *)createTimerWithTarget:(id)target
                                   selector:(SEL)sel
                             startTimer:(NSTimeInterval)start
                               interval:(NSTimeInterval)interval
                                  repet:(BOOL)repet
                                  async:(BOOL)async;
    
    /*
     第一个参数:name,传入需要终止的定时器的名字(名字来源于利用上面的 api 创建定时器时返回的定时器名字)
     */
    + (void)stopTimerWithName:(NSString *)name;
    
    @end
    

    .m文件代码如下:

    #import "GQTimer.h"
    
    static NSMutableDictionary *muDict;
    dispatch_semaphore_t semapore_;
    
    @implementation GQTimer
    
    + (void)initialize {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            muDict = [NSMutableDictionary dictionary];
            semapore_ = dispatch_semaphore_create(1);
        });
    }
    
    + (NSString *)createTimerWithTask:(void(^)(void))block startTimer:(NSTimeInterval)start interval:(NSTimeInterval)interval repet:(BOOL)repet async:(BOOL)async {
    
        if (!block || start < 0 || (repet && interval <= 0)) return nil;
        dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) : 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)), (uint64_t)(interval * NSEC_PER_SEC), 0);
        
        dispatch_semaphore_wait(semapore_, DISPATCH_TIME_FOREVER);
        //定时器的标识
        NSString *name = [NSString stringWithFormat:@"%zd",muDict.count];
        muDict[name] = timer;
        dispatch_semaphore_signal(semapore_);
        
        dispatch_source_set_event_handler(timer, ^{
            block();
            if (!repet) {
                [self stopTimerWithName:name];
            }
        });
        //启动定时器
        dispatch_resume(timer);
        return name;
    }
    
    + (NSString *)createTimerWithTarget:(id)target
                                   selector:(SEL)sel
                             startTimer:(NSTimeInterval)start
                               interval:(NSTimeInterval)interval
                                  repet:(BOOL)repet
                                  async:(BOOL)async {
        if (!target || !sel || start < 0 || (repet && interval <= 0)) return nil;
        
        return [self createTimerWithTask:^{
            if ([target respondsToSelector:sel]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                [target performSelector:sel];
    #pragma clang diagnostic pop
            }
        } startTimer:start interval:interval repet:repet async:async];
    }
    
    + (void)stopTimerWithName:(NSString *)name {
        
        if (name.length == 0) return;
        
        dispatch_semaphore_wait(semapore_, DISPATCH_TIME_FOREVER);
        
        dispatch_source_t timer = muDict[name];
        if (timer) {
            dispatch_source_cancel(timer);
            [muDict removeObjectForKey:name];
        }
        dispatch_semaphore_signal(semapore_);
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS GCD定时器封装

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