如何在 ReactiveCocoa 中使用 sendError

How to use sendError in ReactiveCocoa

我是反应式 Cocoa 的新手,到目前为止非常喜欢它。

我创建了一个注册页面。如果用户名和密码有效,我启用注册按钮。对于登录按钮,我做了以下操作:

[[[[self.registerButton rac_signalForControlEvents:UIControlEventTouchUpInside]
        doNext:^(id x) {
            [MBProgressHUD showHUDAddedTo:self.view animated:YES];
            self.registerButton.enabled = NO;
        }]
        flattenMap:^RACStream *(id value) {
            Login *login = [Login new];
            return [login registerSignalWithName:self.usernameTextField.text
                                     andPassword:self.passwordTextField.text];
        }]
        subscribeNext:^(NSDictionary *result) {
            [MBProgressHUD hideHUDForView:self.view animated:YES];
            // Go to next page
            }
        error:^(NSError *error) {
            [MBProgressHUD hideHUDForView:self.view animated:YES];
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                            message:error.localizedDescription
                                                           delegate:self
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
        }];

我的问题:如果用户名已经存在我 return 一个错误。但是如果我 return 出错,那么 registerButton 上 rac_signalForControlEvents 的订阅将结束!我不会再收到任何信号,我的 registerButton 也不会再有反应。根据文档,这是正确的行为。

另一方面:如果我在出现错误时使用 sendNext 而不是 sendError,我在 sendNext 上有不同的 return 类型(错误或成功时带有结果的字典)。那也不好。所以错误在这种情况下不可用,因为它不允许简单的错误处理。

该问题的正确反应解决方案是什么?

您可以使用 catch: 来达到这个目的。

[[[[self.registerButton rac_signalForControlEvents:UIControlEventTouchUpInside]
    doNext:^(id x) {
        [MBProgressHUD showHUDAddedTo:self.view animated:YES];
        self.registerButton.enabled = NO;
    }]
    flattenMap:^RACStream *(id value) {
        Login *login = [Login new];
        return [[login registerSignalWithName:self.usernameTextField.text
                                  andPassword:self.passwordTextField.text]
        catch:^RACSignal *(NSError *error) {
            UIAlertView *alert =
            [[UIAlertView alloc] initWithTitle:@"Error"
                                       message:error.localizedDescription
                                      delegate:self
                             cancelButtonTitle:@"OK"                                         
                             otherButtonTitles:nil];
            [alert show];
            return [RACSignal empty];
        }]; 
    }]
    subscribeNext:^(NSDictionary *result) {
        [MBProgressHUD hideHUDForView:self.view animated:YES];
    }
    error:^(NSError *error) {}];

catch: 的工作方式与 flattenMap: 类似,但 catch:error 事件做出反应,而不是 next 事件。