Overall, it looks as though the code would do what you want it to do. I don't see any cause for concern on deadlock. Was there a specific area you thought might deadlock?
I can give you a few suggestions on the code.
You've clearly seen that ReactiveCocoa has the concept of a scheduler (RACScheduler
), and this class allows you to replace the imperative use of dispatch queues. This signal above:
return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
dispatch_async(backgroundQueue, ^{
NSLog(@" saving depending ChildStep %@ of parent step:%@", ctx, parent);
[subscriber sendCompleted];
});
return nil;
}];
Can be rewritten using -subscribeOn:
:
RACScheduler *backgroundScheduler = [[RACScheduler alloc] initWithName:nil targetQueue:backgroundQueue];
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
NSLog(@" saving depending ChildStep %@ of parent step:%@", ctx, parent);
[subscriber sendCompleted];
return nil;
}] subscribeOn:backgroundScheduler];
Next, the way you're using sequences can be simplified. Instead of converting the sequences to signals, you could pass a sequence to +[RACSignal concat:]
. For example, instead of:
RACSignal *contexts = [[@[@"ChildStep 1", … @"ChildStep N"] rac_sequence] signalWithScheduler:RACScheduler.immediateScheduler];
contexts = [contexts map:^(id ctx) {
return [self executeRequestAsynchChildStep:ctx withParent:parent];
}];
return [contexts concat];
You can drop the use of -signalWithScheduler:
, and apply +concat:
:
RACSequence *contexts = [@[@"ChildStep 1", … @"ChildStep N"] rac_sequence];
contexts = [contexts map:^(id ctx) {
return [self executeRequestAsynchChildStep:ctx withParent:parent];
}];
return [RACSignal concat:contexts];
Hope that helps.
PS. You can learn a lot by following the ReactiveCocoa discussions.