Skip to content

Latest commit

 

History

History
78 lines (51 loc) · 2.69 KB

SingleTimer.md

File metadata and controls

78 lines (51 loc) · 2.69 KB

SingleTimer

在业务中难免会遇到多处使用定时器的需求,创建多个定时器并不现实,本案提供一种多个业务共用一个定时器的方案。

TimerObserver

每一个需要定时器的业务抽象成TimerObserver,他只需要提供一个唯一id,以及定时器的回调即可,没有多余的事件回调。在-onTimer中,业务方只需要更新自身提供的计数变量(counter)即可,方法简单就会更方便对接现有业务。

@protocol TimerObserver <NSObject>

- (NSString *) uniqueId;

@optional
- (void) onTimer;
@end

SingleTimer

SingleTimer是对定时器的抽象,通过-addTimerObserver:添加需要定时器的业务方观察者,在内部只有不少于一个观察者的情况下才会开启定时器,如果通过-removeTimerObserver:移除观察者之后,观察者数量为0则会自动停止定时器。

@interface SingleTimer : NSObject

- (instancetype) initWithInterval:(NSTimeInterval)intervalValue;

- (void) addTimerObserver:(id<TimerObserver>)observer;
- (void) removeTimerObserver:(id<TimerObserver>)observer;
@end

业务方可能是模型,也可能是视图,如果它需要定时器,只需要遵守TimerObserver即可。使用起来大概如下:

// in some ViewContrller.m

- (void) onAdd{
    [self.timer addTimerObserver:self];
}

#pragma mark - TimerObserver

- (NSString *)uniqueId{
    return @"Home-ViewController";
}

- (void)onTimer{
    self.counter ++;
    self.displayLabel.text = [NSString stringWithFormat:@"%ld",(long)self.counter];
}

SingleTimer内部由定时器_SingleInnerTimer来执行定时打点任务,本质上是对NSTimer的封装,增加了pauserestart功能。_TimerCollection负责对观察者的存储,它并不是直接存储id<TimerObserver>,而是存储_TimerObserver这个私有类的实例。并且通过为NSObject提供一个disposeBag来存储一个token(_TimerToken),在id<TimerObserver>销毁的时候(调用dealloc)执行token的onDispose回调,在内部移除_TimerCollection存储的观察者。

// in SingleTimer.m

- (void) addTimerObserver:(id<TimerObserver>)observer{
    
    __weak typeof(self) weakSelf = self;

    __block _TimerObserver * innerObserver = [_TimerObserver new];
    innerObserver.object = observer;
    
    _TimerToken * token = [[_TimerToken alloc] initWithKey:key];
    token.onDispose = ^(NSString *uniqueId) {
        __strong typeof(self) strongSelf = weakSelf;
        [strongSelf removeObserverForKey:uniqueId];
    };
    [innerObserver.object.disposeBag addToken:token];
    [_collection addObserver:innerObserver forKey:key];
}