I am still fairly new in the ReactiveCocoa world and I just wanted to get this common scenario clarified. I noticed that other people are struggling with this matter on GitHub and SO, but I am still missing a proper answer.
The following example does work, but I saw that Justin Summers says that subscriptions-within-subscriptions or subscriptions in general could be code smell. Therefor I want to try and avoid bad habits when learning this new paradigm.
So, the example (using MVVM) is pretty simple:
- A ViewController contains a login button which is connected to a login command in the viewmodel
- The ViewModel specifies the command action and simulates some network request for this example.
- The ViewController subscribes to the command's executingSignals and is able to differentiate the three types of returns: next, error and complete.
And the code.
1 (ViewController):
RAC(self.loginButton, rac_command) = RACObserve(self, viewModel.loginCommand);
2 (ViewModel):
self.loginCommand = [[RACCommand alloc] initWithEnabled:canLoginSignal
signalBlock:^RACSignal *(id input) {
return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
BOOL success = [username isEqualToString:@"user"] && [password isEqualToString:@"password"];
// Doesn't really make any sense to use sendNext here, but lets include it to test whether we can handle it in our viewmodel or viewcontroller
[subscriber sendNext:@"test"];
if (success)
{
[subscriber sendCompleted];
} else {
[subscriber sendError:nil];
}
// Cannot cancel request
return nil;
}] materialize];
}];
3 (ViewController):
[self.viewModel.loginCommand.executionSignals subscribeNext:^(RACSignal *execution) {
[[execution dematerialize] subscribeNext:^(id value) {
NSLog(@"Value: %@", value);
} error:^(NSError *error) {
NSLog(@"Error: %@", error);
} completed:^{
NSLog(@"Completed");
}];
}];
How would you do this in a more ReactiveCococa-kind-a-way?