I have a view controller, which has two signals. One is the pull down to refresh signal, the other is the pull up to load more signal. There are two common scenes:
Refer to the document, I found that switchToLatest operator could forbid the same signal running simultaneously. However it's not perfect, because the switchToLatest is start a new signal when the old signal is not finished, and send the new signal's next to the subscriber. What I want is if a signal is running, the new signal should not trigger.
In the no RAC world, I have to maintain a isLoading state; and before trigger pull down or pull up signal, I will check the isLoading and determine the signal should be triggered.
Is there any elegant way in RAC world to remove the isLoading state?
In general you need to send these state changes in the signal.
Try using RACSubject
for state changes for each of the separate processes (pull up and pull down). Each of them should subscribe on opposite and own RACSubject
signal, and during new trigger call apply following operator:
- (RACSignal *)combineLatestWith:(RACSignal *)signal;
Something like this:
RACSubject *pullUpStateChanged = [RACSubject subject];
RACSubject *pullDownStateChanged = [RACSubject subject];
RACSignal *stateChangeTrigger = [pullUpStateChanged combineLatestWith:pullDownStateChanged]
[stateChangeTrigger
filter:^BOOL(RACTuple *tuple) {
/// second item should contains tuple with 2 states
/// based on this value you can reject some of the flows
}]
flattenMap:^RACStream *(id value) {
}];
One notice: combineLatestWith:
will start working when each of the signals will fire at least once. That's why send initial state @NO
(or other value). Otherwise you could use your real triggers instead.
P.S. I didn't verify and build provided code in Xcode.
UPDATE: All you need to forward you pullUp and pullDown RACSignal's
data to the subjects via sendNext:
on appropriate RACSubject
. Using of the subjects here is little bit overhead, but you need to start work before the state in which both of the signals have fired (combineLatestWith: unfortunately will not fire if both of the the signals aren't ready). That's why you need to use RACSubjects as a mediator between your real triggers and actual actions.
UPDATE2: Actually it's interesting challenge and I've tried to implement this kind of thing. And I've faced with one issue. That while using combineLatestWith: you will forced to get updates not only from actual trigger but with opposite also. And you need to distinguish requests for changes with some ID. I've placed full implementation here