美文网首页
GCD定时器封装(OC)

GCD定时器封装(OC)

作者: 蓝雪清晨 | 来源:发表于2023-08-14 16:52 被阅读0次

    GCXTimer.h

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface GCXTimer : NSObject
    
    /**
     *  task 执行的任务
     *  start   开始间隔时间
     *  interval    timer间隔时间
     *  repeats 是否重复
     *  async   是否异步
     */
    + (NSString *)execTask:(void(^)(void))task
                     start:(NSTimeInterval)start
                  interval:(NSTimeInterval)interval
                   repeats:(BOOL)repeats
                     async:(BOOL)async;
    
    /**
     *  target  添加定时器的目标
     *  selector   回调方法
     *  interval    timer间隔时间
     *  repeats 是否重复
     *  async   是否异步
     */
    + (NSString *)execTarget:(id)target
                    selector:(SEL)selector
                       start:(NSTimeInterval)start
                    interval:(NSTimeInterval)interval
                     repeats:(BOOL)repeats
                       async:(BOOL)async;
    
    /**
     * 取消定时器
     * task 定时器的唯一标识
     */
    + (void)cancelTimerTask:(NSString *)task;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    GCXTimer.m

    #import "GCXTimer.h"
    
    @interface GCXTimer()
    
    @end
    
    @implementation GCXTimer
    
    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);
        });
        
    }
    
    /**
     *  task        执行的任务
     *  start       开始间隔时间
     *  interval    timer间隔时间
     *  repeats     是否重复
     *  async       是否异步
     *  返回值为定时器的唯一标识
     */
    + (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;
        
        //队列
        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, start*NSEC_PER_SEC), interval*NSEC_PER_SEC, 0);
        
        //加锁
        dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
        
        //定时器的唯一标识
        NSString *name = [NSString stringWithFormat:@"%zd",timers_.count];
        
        timers_[name] = timer;
        
        //发送信号(解锁)
        dispatch_semaphore_signal(semaphore_);
    
        //设置回调
        dispatch_source_set_event_handler(timer, ^{
            task();
            if (!repeats) {//不重复的任务
                [self cancelTimerTask:name];
    //            dispatch_source_cancel(timer);
            }
        });
        //启动定时器
        dispatch_resume(timer);
            
        return name;
    }
    
    /**
     *  target  添加定时器的目标
     *  selector   回调方法
     *  interval    timer间隔时间
     *  repeats 是否重复
     *  async   是否异步
     */
    + (NSString *)execTarget:(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];
    }
    
    /**
     * 取消定时器
     * task 定时器的唯一标识
     */
    + (void)cancelTimerTask:(NSString *)task {
        
        if (task.length == 0) {
            return;
        }
        //加锁
        dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
        dispatch_source_t timer = timers_[task];
        if (timer) {
            dispatch_source_cancel(timers_[task]);
            [timers_ removeObjectForKey:task];
        }
        
        //发送信号(解锁)
        dispatch_semaphore_signal(semaphore_);
    
    }
    
    @end
    
    

    使用示例:

    @property (nonatomic, copy) NSString *timerId;/**< 定时器标识 */
    
    //创建定时器
    self.timerId = [GCXTimer execTask:^{
            //自己的代码块
    } start:0.0 interval:1.0f repeats:YES async:NO];
    
    //取消定时器
    [GCXTimer cancelTimerTask:self.timerId];
    

    相关文章

      网友评论

          本文标题:GCD定时器封装(OC)

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