I'm using ReactiveCocoa to compose complex signal of the following structure:
RACSignal* data1FromNetwork = ...;
RACSignal* data1FromNetworkHub = [data1FromNetwork replayLazily];
RACSignal* derivedData = [data1FromNetworkHub flattenMap:...];
RACSignal* data2FromNetwork = ...;
RACSignal* result = [RACSignal combineLatest:@[data1FromNetworkHub, derivedData, data2FromNetwork] reduce:...];
Signal data1FromNetwork
is implemented as a network call, but has multiple subscribers - derivedData
and in combineLatest:reduce:
. So to avoid duplicating network calls, I use replayLazily
to create a hub signal, that can be used for multiple subscriptions.
When I cancel result
, all subscriptions to the hub signal get disposed, but the subscription between the hub signal and data1FromNetwork
itself remains. So data1FromNetwork
does not get cancelled. Underlying network request completes, RACReplaySubject
created inside replayLazily
gets notified, and data process stops at this point without any visible effect.
This is acceptable, but can be done better - I'd like all network activity to be cancelled as well. Can this be achieved using built-in RAC operators?
It might be represented like that using -[RACMulticastConnection autoconnect]
:
RACSignal* data1FromNetwork = ...;
RACSignal* data1FromNetworkHub = [[data1FromNetwork publish] autoconnect];
// Or below if you want replaying behavior.
// RACSignal* data1FromNetworkHub = [[data1FromNetwork multicast:RACReplaySubject.subject] autoconnect];
RACSignal* derivedData = [data1FromNetworkHub flattenMap:...];
RACSignal* data2FromNetwork = ...;
RACSignal* result = [RACSignal combineLatest:@[data1FromNetworkHub, derivedData, data2FromNetwork] reduce:...];
When the signal returned by -autoconnect
got to have no subscribers, the underlying signal (data1FromNetwork
in this case) would be disposed.