Reputation: 18316
I often use ReactiveCocoa to track the latest value of some variable, like the text in a text field. Sometimes these latest values are actually themselves computed, in a way that multiple subscriptions causes the computations to happen multiple times. Often it would be significantly more efficient to merge these computations.
What I would like to use is RACSignal* sharedComputationLatest = complicatedLatestValue.publish.autoconnect
, but then when new subscribers subscribe to the shared computation signal they are not told the latest value.
Is there a variant of publish
, some sort of publishLatest
, that already exists and does what I need? If not, does it already exist and have a name in .Net's Rx?
Update: It turns out that autoconnect
has slightly different semantics than I thought, namely that if the number of subscribers goes to zero and then back up there is no re-connection. I needed the re-connection bit, so I implemented my own method (in an answer below).
Upvotes: 2
Views: 649
Reputation: 18316
Here's a custom implementation (note: not thread safe):
-(RACSignal*) publishLatestAutoreconnect {
__block int32_t subscriberCount = 0;
__block RACDisposable* subscription = nil;
__block RACReplaySubject* publishSubject = nil;
return [RACSignal createSignal:^RACDisposable*(id<RACSubscriber> subscriber) {
__block RACDisposable* _subscriberDisposable = nil;
// auto[re]connect if we had no subscribers
subscriberCount++;
if (subscriberCount == 1) {
publishSubject = [RACReplaySubject replaySubjectWithCapacity:1];
subscription = [self subscribe:publishSubject];
}
// forward to subscriber
_subscriberDisposable = [publishSubject subscribe:subscriber];
return [RACDisposable disposableWithBlock:^{
// stop forwarding to subscriber
[_subscriberDisposable dispose];
// disconnect if we now have no subscribers
subscriberCount--;
if (subscriberCount == 0) {
[subscription dispose];
subscription = nil;
publishSubject = nil;
}
}];
}];
}
Upvotes: 1