使用 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.");
}];
}];
最佳答案
由于错误会自动转移到 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);
}];
关于ios - 将 RACCommand 组合成一个共同结果的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19867331/