ReactiveObjC
ReactiveObjC copied to clipboard
a delayed signal may not enter subscribeNext block!!!
Recently, we found and proved a bug when use rac delay method in OC version. a delayed signal may not enter subscribeNext block, which cause great effect on followed up process.
As we can see from the source code, a delayed signal's "subcribeNext" and "completed" block was setted in RACQueueScheduler, which supported by GCD.
void (^schedule)(dispatch_block_t) = ^(dispatch_block_t block) {
RACScheduler *delayScheduler = RACScheduler.currentScheduler ?: scheduler;
RACDisposable *schedulerDisposable = [delayScheduler afterDelay:interval schedule:block];
[disposable addDisposable:schedulerDisposable];
};
RACDisposable *subscriptionDisposable = [self subscribeNext:^(id x) {
schedule(^{
[subscriber sendNext:x];
});
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
schedule(^{
[subscriber sendCompleted];
});
}];
In "RACQueueScheduler.m Line:80", we could see clearly that dispatch_after realizes the delay function:
dispatch_after([self.class wallTimeWithDate:date], self.queue, ^{
if (disposable.disposed) return;
[self performAsCurrentScheduler:block];
});
The problem is, when delayed taskes are handled by dispatch_after, the GCD can not dispatch these taskes serially. which causing a delayed signal completed firstly and without enter subcribeNext.
we can prove it by code blow:
for (NSInteger i = 0; i < 10000; i++) {
dispatch_after([self wallTimeWithDate:[NSDate dateWithTimeIntervalSinceNow:0.0]], dispatch_get_main_queue(), ^{
NSLog(@"index = %@", @(i));
});
}
from console Log: index is not progressive increasing.
One more thing, if give up the dispatch_walltime paramter in dispatch_after, using dispatch_time instead, it will work normally.
Hope it will fix soon.
Best wishes.
How large is the delay interval?