使用ReactiveCocoa 2.0,有没有更好的方法来执行以下操作,而无需实现/取消实现,并且仍然能够从3个信号中的任何一个中捕获错误,而无需重复代码?
有3个登录按钮。每个返回对应于异步“登录”API调用的信号。完成后,它们将返回用户对象,错误和/或完成。
// Login signals
_loginButton.rac_command = [[RACCommand alloc] initWithEnabled:loginValid signalBlock:^RACSignal *(id input) {
return [[API doLogin:_usernameField.text password:_passwordField.text] materialize];
}];
_fbLoginButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return [[API doFacebookLogin] materialize];
}];
_twLoginButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return [[API doTwitterLogin] materialize];
}];
// Login response from any of the 3 signals
[[RACSignal
merge:@[_loginButton.rac_command.executionSignals,
_fbLoginButton.rac_command.executionSignals,
_twLoginButton.rac_command.executionSignals]]
subscribeNext:^(RACSignal *loginSignal) {
RACSignal * s = [loginSignal dematerialize];
[s subscribeNext:^(User *x) {
NSLog(@"user: %@", x);
} error:^(NSError *error) {
NSLog(@"error: %@", error);
} completed:^{
NSLog(@"Completed.");
}];
}];
答案 0 :(得分:8)
由于错误会自动转移到errors
信号,因此您通常无需自行处理实现或任何问题。事实上,这种(潜在的)复杂性是错误特殊行为的最初动机。
只需合并错误信号并在一个地方处理它们:
[[RACSignal
merge:@[
_loginButton.rac_command.errors,
_fbLoginButton.rac_command.errors,
_twLoginButton.rac_command.errors,
]]
subscribeNext:^(NSError *error) {
NSLog(@"error: %@", error);
}];
作为旁注,您还可以使用-flatten
- 而不是内部订阅 - 来简化登录响应的处理:
[[[RACSignal
merge:@[
_loginButton.rac_command.executionSignals,
_fbLoginButton.rac_command.executionSignals,
_twLoginButton.rac_command.executionSignals,
]]
// Flattens the signal of `User` signals by one level. The result is
// one signal of `User`s.
//
// This avoids any need for an inner subscription.
flatten]
subscribeNext:^(User *x) {
// This means that a login request completed as well, so there's no need
// for a separate `completed` block.
NSLog(@"user: %@", x);
}];