hiroshi
hiroshi

Reputation: 7251

ReactiveCocoa finally never be called with already completed replaySubject. Is it expected behavior?

Is this expected behavior?

RACSubject *subject = [RACReplaySubject replaySubjectWithCapacity:1];
[subject sendCompleted];
[subject finally:^{
    NSLog(@"never called");
}];
[subject subscribeCompleted:^{
    NSLog(@"called");
}];

If so, how do I have finally like block? Do I need like this?

void (^block)() = ^ {
    NSLog(@"like finally!");
};
[subject subscribeError:^(NSError *error) {
    block();
} completed:^{
    block();
}];

EDIT: For those who misunderstand what finally do like me, the document for renamed doFinished in RAC 3.0 may help you understand, instead of the 2.X document.

Upvotes: 0

Views: 345

Answers (1)

Ian Henry
Ian Henry

Reputation: 22403

It's actually unrelated to the fact that the signal has already completed. Consider this:

RACSubject *subject = [RACSubject subject];
[subject finally:^{
    NSLog(@"never called");
}];
[subject subscribeCompleted:^{
    NSLog(@"called");
}];
[subject sendCompleted];

Still never called! Why? Because finally: returns a new signal; it doesn't modify the existing signal. The new signal will perform those side effects whenever it sends a completed or error to one of its subscribers. If it doesn't have any subscribers, those side effects will never take place. So now let's subscribe to the signal that finally: returns:

RACSubject *subject = [RACReplaySubject replaySubjectWithCapacity:1];
[subject sendCompleted];
[[subject finally:^{
    NSLog(@"called now!");
}] subscribeCompleted:^{
    NSLog(@"called");
}];

That works, but might not be what you actually want. finally: doesn't inject side effects into the signal, it injects side effects into each subscription to the signal. So the following thing:

RACSubject *subject = [RACReplaySubject replaySubjectWithCapacity:1];
[subject sendCompleted];
RACSignal *signalWithFinally = [subject finally:^{
    NSLog(@"finally block");
}];
[signalWithFinally subscribeCompleted:^{
    NSLog(@"first subscriber completed");
}];
[signalWithFinally subscribeCompleted:^{
    NSLog(@"second subscriber completed");
}];

Will perform the finally: block twice, which may not be what you want. subscribeError:completed: may be a better choice for your use case.

Upvotes: 2

Related Questions