To bind some action to the button click one can use just a custom RACSignal. But then you have to add three more things in every case:
1. Disable button, while action is performing;
2. Show, that action is in progress;
3. Disable button, if input is incorrect and button should not be able to be tapped.
Instead, if you use RACCommand, you get all these things in a box.
Let’s say, we want to bind RACCommand verifyPhoneCommand to a button. We can create a command in a lazy property in a ViewModel:
- (RACCommand *)verifyPhoneCommand
{
if (! _verifyPhoneCommand) {
_verifyPhoneCommand = [[RACCommand alloc] initWithEnabled:self.phoneValidSignal
signalBlock:^RACSignal * _Nonnull(id _Nullable input) {
return [self verifyPhone];
}];
}
return _verifyPhoneCommand;
}
Here phoneValidSignal is this signal, that is formed by observing a phone variable:
- (RACSignal *)phoneValidSignal
{
if (!_phoneValidSignal) {
_phoneValidSignal = [RACObserve(self, phone) map:^id(NSString *phone) {
return @(phone.length > 0);
}];
}
return _phoneValidSignal;
}
We pass a RACSignal verifyPhone to the RACCommand to do a job:
- (RACSignal *)verifyPhone
{
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[[PhoneManager sharedManager]
requestVerifyPhone:self.phone
success:^{
[subscriber sendNext:@(YES)];
[subscriber sendCompleted];
} failure:^(NSError *error) {
[subscriber sendError:error];
}];
return nil;
}];
}
This is how we bind a RACCommand to a button:
self.smsRequestButton.rac_command = self.viewModel.verifyPhoneCommand;
To track execution of a RACCommand and show an activity indicator we can use executing property:
[self.viewModel.verifyPhoneCommand.executing subscribeNext:^(NSNumber* _Nullable x) {
if (x.boolValue) {
[self.spinnerView startAnimating];
}
else {
[self.spinnerView stopAnimating];
}
}];
If errors happen during RACCommand execution we can process those errors:
[self.viewModel.verifyPhoneCommand.errors subscribeNext:^(NSError * _Nullable error) {
[ErrorUtil showError:error from:self onRepeat:^{
}];
}];