美文网首页
iOS 全局定时器

iOS 全局定时器

作者: moxacist | 来源:发表于2018-05-02 14:51 被阅读167次

我们在项目开发过程中有时会遇到这种需求:

  • tableview等列表中会含有多个倒计时的UI
  • 在启动某个操作就需要定时器重复执行某个动作(比如上传地理坐标,心跳)

我的做法是开启个全局定时器,有对象要计时的时候调用addNotificationObserver:(id)observer type:(MDGlobalTimerType)type selector:(SEL)seletor把注册到MDGlobalTimer类里,

在对象delloc或者释放的时候调用removeNotificationObserver:(id)observer type:(MDGlobalTimerType)type方法注销对象

然后在add的方法中开启一个定时器(已开启就不开了)
在remove方法中判断数组里还有对象没,没有的话表明没有需要计时的对象,就停止定时器并销毁
计时:每过一定时间(这里设置成1s),发出通知(add方法里已经注册了通知),然后执行对象的方法,进行刷新UI

- (void)addNotificationObserver:(id)observer type:(MDGlobalTimerType)type selector:(SEL)seletor{
   
    BOOL addNotification = NO;
    NSString *notificationName = nil;
    switch (type) {
        case MDGlobalTimerTypeOneSecond:
        {
            NSMutableSet *secondsObservers = [NSMutableSet setWithSet:_observers[kOneSecond]];
            if (![secondsObservers containsObject:observer]) {
               [secondsObservers addObject:observer];
                addNotification = YES;
                notificationName = notification_kOneSecond;
                _observers[kOneSecond] = secondsObservers;
            }
            
        }
            break;
        case MDGlobalTimerTypeHalfMinute:
        {
            NSMutableSet *halfMinuteObservers = [NSMutableSet setWithSet:_observers[kHalfMinute]];
            if (![halfMinuteObservers containsObject:observer]) {
                [halfMinuteObservers addObject:observer];
                addNotification = YES;
                notificationName = notification_kHalfMinute;
                _observers[kHalfMinute] = halfMinuteObservers;
            }
            
        }
            break;
        case MDGlobalTimerTypeOneMinute:
        {
            NSMutableSet *oneMinuteObservers = [NSMutableSet setWithSet:_observers[kOneMinute]];
            if (![oneMinuteObservers containsObject:observer]) {
                [oneMinuteObservers addObject:observer];
                addNotification = YES;
                notificationName = notification_kOneMinute;
                _observers[kOneMinute] = oneMinuteObservers;
            }   
        }
            break;
        default:
            break;
    }
    
    //添加通知
    if (addNotification) {
        [[NSNotificationCenter defaultCenter] addObserver:observer selector:seletor name:notificationName object:nil];
    }
    
    //开启定时器
    [self startTiming];
    
}
- (void)removeNotificationObserver:(id)observer type:(MDGlobalTimerType)type{
    
    NSString *notificationName = nil;
    switch (type) {
        case MDGlobalTimerTypeOneSecond:
        {
            NSMutableSet *secondsObservers = _observers[kOneSecond];
            [secondsObservers removeObject:observer];
            _observers[kOneSecond] = secondsObservers;
            notificationName = notification_kOneSecond;
        }
            break;
        case MDGlobalTimerTypeHalfMinute:
        {
            NSMutableSet *halfMinuteObservers = _observers[kHalfMinute];
            [halfMinuteObservers removeObject:observer];
            _observers[kHalfMinute] = halfMinuteObservers;
            notificationName = notification_kHalfMinute;
        }
            break;
        case MDGlobalTimerTypeOneMinute:
        {
            NSMutableSet *oneMinuteObservers = _observers[kOneSecond];
            [oneMinuteObservers removeObject:observer];
            _observers[kOneSecond] = oneMinuteObservers;
            notificationName = notification_kOneMinute;
        }
            break;
        default:
            break;
    }
    
    //移除监听
    [[NSNotificationCenter defaultCenter] removeObserver:observer name:notificationName object:nil];
    //移除空set
    [_observers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSMutableSet * _Nonnull obj, BOOL * _Nonnull stop) {
        if (obj.count == 0) {
            [_observers removeObjectForKey:key];
        }
    }];
    
    //关闭定时器
    [self stopTiming];
}

启动定时器:

static NSString *const kOneSecond = @"kOneSecond";
static NSString *const kHalfMinute = @"kHalfMinute";
static NSString *const kOneMinute = @"kOneMinute";

@implementation MDGlobalTimer{
    dispatch_source_t _timer;
    int _seconds;
    NSMutableDictionary <NSString *,NSMutableSet*> *_observers;
}

+ (id)allocWithZone:(struct _NSZone *)zone{
    return [self sharedInstance];
}

+ (instancetype)sharedInstance{
    static MDGlobalTimer *timer;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        timer = [[super allocWithZone:nil] init];
        timer->_observers = @{}.mutableCopy;
        
    });
    return timer;
}


/** 开启定时器 */
- (void)startTiming{
    if (_timer) {
        return;
    }
    _seconds = 0;
    _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_timer, ^{
        _seconds++;
        dispatch_sync(dispatch_get_main_queue(), ^{
            //发送s
            if (_observers[kOneSecond].count > 0) {
                [[NSNotificationCenter defaultCenter] postNotificationName:notification_kOneSecond object:nil];
            }
            //发送半分钟通知
            if (_seconds%30 == 0 && _observers[kHalfMinute].count > 0) {
                [[NSNotificationCenter defaultCenter] postNotificationName:notification_kHalfMinute object:nil];
            }
            
            //发送1分钟通知
            if (_seconds%60 == 0 && _observers[kOneMinute].count > 0) {
                [[NSNotificationCenter defaultCenter] postNotificationName:notification_kOneMinute object:nil];
                _seconds = 0;
            }
        });
    });
    dispatch_resume(_timer);
}

/** 结束定时器 */
- (void)stopTiming{
    if (_timer && _observers.count == 0) {
        dispatch_source_cancel(_timer);
        _timer = nil;
    }
}

这里由于工程中只有分、秒、30s的定时需求,所以只写死了这三个,如果有更细节的定时,可以在add方法里加计时间隔,并在计时时以最大公因数判断

如果有什么不对的地方,希望评论指正下œ∑®
MDGlobalTimer-demo

相关文章

  • iOS 全局定时器

    我们在项目开发过程中有时会遇到这种需求: tableview等列表中会含有多个倒计时的UI 在启动某个操作就需要定...

  • 无标题文章

    iOS NSTimer使用详解-开启、关闭、移除 定时器定时器详解ios定时器关闭定时器NSTimer 1、要使用...

  • iOS进阶-谈谈定时器

    目录 iOS提供定时器API 定时器开发中的坑 一、 iOS提供定时器API 二、定时器开发中的坑 2.1、必须办...

  • 定时器

    定时器 兼容ios

  • iOS中的定时器

    点击这里>> cocoaChina: iOS中的定时器 iOS中定时器有三种,分别是NSTimer、CADispl...

  • GCD定时器使用

    iOS中的常用定时器分为这几类: NSTimer CADisplayLink GCD定时器 选择GCD定时器原因:...

  • iOS:NSTimer的几种创建方式

    在iOS开发中,经常会用到定时器,iOS中常用的定时器有三种:NSTimer,GCD,CADisplayLink。...

  • iOS Timer

    iOS开发中定时器经常会用到,iOS中常用的定时器有三种,分别是NSTime,CADisplayLink和GCD。...

  • 每日笔记

    1、通过safari打开网页 2、iOS的几种定时器及区别 iOS的几种定时器及区别 3、long long类型 ...

  • iOS三大定时器

    iOS开发中定时器经常会用到,iOS中常用的定时器有三种,分别是NSTime,CADisplayLink和GCD。...

网友评论

      本文标题:iOS 全局定时器

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