Кой е най-добрият начин за нулиране на сигнал на таймера?

Трябва да извличам данни от сървъра на всеки 5 минути. Ако изтегля опресняването, също трябва да извлека данни от сървъра и нулиране на таймера.

Кодът по-долу е решението сега, изглежда работи добре. Просто се чудя как да опростя кода? Вероятно има по-добър начин в 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];
        }];
    }];

person JerryZhou    schedule 21.08.2015    source източник


Отговори (2)


Най-чистият начин, за който мога да се сетя, е използването на RACReplaySubject, изпращане на interval сигнала от 300 и след това превключване към последния сигнал, изпратен всеки път, когато блокът се задейства.

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];
}];
person Charles Maria    schedule 21.08.2015
comment
Да, вашият код е много по-чист от моя. Просто не съм запознат с RACReplaySubject. - person JerryZhou; 21.08.2015
comment
RACReplaySubject е нещо като ръчен сигнал. Това е като еквивалент на променлива променлива на функционалния реактивен свят. Вие ръчно му казвате кога да изпрати next, error и completed. Тъй като има капацитет 1, той съхранява последното изпратено next и го препраща към всички нови абонаменти. - person Charles Maria; 21.08.2015
comment
Тествах вашия код, само един малък проблем (или може да е негова характеристика): закъснението може да забави 300 или 301 секунди и не харесва таймера с withLeeway, за да върне интервала обратно; Това, което таймерът дава, е, че ако е 301 секунди, следващия път може да се върне на 209 секунди, за да стане стабилен. - person JerryZhou; 21.08.2015
comment
Но вашият код е добро предложение за мен. Просто мисля, че 300 средно би било по-добре. Просто защото акумулиращият ефект от офсета би станал огромен. - person JerryZhou; 21.08.2015
comment
Редактирано за използване на таймер. - person Charles Maria; 21.08.2015
comment
Имам редакция за включване на стартов сигнал. sendNext:[RACSignal return:nil] - person JerryZhou; 21.08.2015
comment
И никога не съм мислил за sendNext: с предишен сигнал вашият отговор разширява хоризонтите ми. - person JerryZhou; 21.08.2015
comment
Радвам се да помогна, надявам се, че е достатъчно добър, за да бъде приетият отговор. - person Charles Maria; 21.08.2015

Бих картографирал refreshSignal към сигнал на таймера. Всеки път, когато refreshSignal изпрати стойност, той се съпоставя със сигнал, изпращащ стойност на всеки пет минути.

Като странична бележка мисля, че тази логика принадлежи към модела на изгледа. Там полученият сигнал може да бъде съпоставен към мрежова заявка с flatMap:. Тогава текуща мрежова заявка ще бъде анулирана, ако потребителят опресни отново бързо.

[[[[refreshSignal startWith:nil]
map:^id(id value) {
    return [[RACSignal interval:5 * 60 onScheduler:[RACScheduler mainThreadScheduler]] startWith:nil];
}]
switchToLatest]
subscribeNext:^(id x) {
    @strongify(self)
    [self.viewModel performFetch];
}];
person andersfrank    schedule 30.08.2015
comment
Благодаря ви за повторението, ще тествам вашето по-късно. - person JerryZhou; 01.09.2015