iosreactive-cocoanstimeintervalracsignal

What's the best way to reset a timer signal?


I need to fetch data from server every 5 minutes. If I do pull down refresh, also need to fetch data from server, and reset the timer.

Below code is the solution now, looks works fine. Just wonder how to simplify the code? Probable there's better way in ReactiveCocoa?

    RACSignal* refreshSignal = [self.refreshControl rac_signalForControlEvents:UIControlEventValueChanged];
    self.timerSignal = [[RACSignal interval:300 onScheduler:[RACScheduler scheduler] withLeeway:2] takeUntil:refreshSignal];
    [self.timerSignal subscribeNext:^(id x) {
        NSLog(@"==========================");
        NSLog(@"[Timer1]");
        [self.viewModel performFetch];
    }];

    [refreshSignal subscribeNext:^(id x) {
        NSLog(@"==========================");
        NSLog(@"[Refresh]");
        [self.viewModel performFetch];
        self.timerSignal = [[RACSignal interval:300 onScheduler:[RACScheduler scheduler] withLeeway:2] takeUntil:refreshSignal];
        [self.timerSignal subscribeNext:^(id x) {
            NSLog(@"==========================");
            NSLog(@"[Timer2]");
            [self.viewModel performFetch];
        }];
    }];

Solution

  • The cleanest way that I can think of would be using a RACReplaySubject, sending interval signals of 300 and then switching to the latest signal sent every time the block is fired.

    self.timerSubject = [RACReplaySubject replaySubjectWithCapacity:1];
    RACSignal * refreshSignal = [self.refreshControl rac_signalForControlEvents:UIControlEventValueChanged];
    RACSignal * timeSignal = [RACSignal interval:300 onScheduler:[RACScheduler scheduler] withLeeway:2];
    [self.timerSubject sendNext:timeSignal];
    
    @weakify(self)
    [[self.timerSubject.switchToLatest merge:refreshSignal] subscribeNext:^(id _) {
        @strongify(self)
        [self.viewModel performFetch];
    }];
    
    [refreshSignal subscribeNext:^(id _) {
        @strongify(self)
        [self.timerSubject sendNext:timeSignal];
    }];