Вопрос

I wonder if it's possible to accumulate results of signals happening between nexts of a particular signal. Similar to

[[[RACSignal
    combineLatest:@[signal1, signal2, signal3]]
    takeUntil:signal4]
    subscribeNext:^(id x) {
        // ...
    }];

But not completing after the first signal4's next.

The scenario I'm working with is I have a viewController1 that presents viewController2. viewController2 allows user to change an object that affects data presented in viewController1. Currently I'm exposing an objectChangedSignal on a viewController2 and listening to it from viewController1.

However, I'd like to receive changes of the object directly from the viewController1 but only after it fires viewWillAppear signal and only if changes happened after viewWillDisappear of viewController1.

Hope it makes sense, thank you.

Это было полезно?

Решение

One way to buffer values is to use -[RACSignal collect], which collects them into an array until the signal completes:

[[[RACSignal combineLatest:@[ s1, s2, s3 ]]
    collect]
    takeUntil:s4]

Howevever, you probably wanted each value to be sent individually on the final signal, not an array of values. You can use -[RACSignal flattenMap:] to flatten those values back into the final signal:

[[[[RACSignal combineLatest:@[ s1, s2, s3 ]]
    collect]
    takeUntil:s4]
    flattenMap:^(NSArray *collected) {

        return [[collected rac_sequence] signal];

    }]

And since you don't want your signal to be completed after s4, you can use -repeat to resubscribe after every time s4 sends a value. If you didn't do this, the -takeUntil: would cause your signal to complete when that happens.

[[[[[RACSignal combineLatest:@[ s1, s2, s3 ]]
    collect]
    takeUntil:s4]
    flattenMap:^(NSArray *collected) {

        return [[collected rac_sequence] signal];

    }]
    repeat]

Note that if any of the combined signals are cold signals, the resubscription will cause their side effects to occur additional times. So you may have to convert them into a hot signal by multicasting them (or the combined signal):

RACMulticastConnection *mc = [[RACSignal combineLatest:@[ s1, s2, s3 ]] publish];
RACDisposable *d = [mc connect];
[[[mc.signal
    takeUntil:s4]
    flattenMap:^(NSArray *collected) {

        return [[collected rac_sequence] signal];

    }]
    repeat]

You may need to explicitly unsubscribe (by disposing d) if your signal would otherwise live infinitely.

(Nota bene, this code is untested.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top