如何在ReactiveCocoa中使用sendError

时间:2015-02-05 09:07:26

标签: ios reactive-cocoa

我是反应性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];
        }];

我的问题:如果是用户名已存在我返回错误。但是如果我返回错误,那么registerButton上的rac_signalForControlEvents的订阅将结束!我将不再获得信号,我的registerButton将不再做出反应。根据文档,这是正确的行为。

另一方面:如果我在发生错误时使用sendNext而不是sendError,我在sendNext上会有不同的返回类型(错误或字典会在成功的情况下显示结果)。这也不好。因此,在这种情况下,错误不可用,因为它不允许简单的错误处理。

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

1 个答案:

答案 0 :(得分:1)

您可以将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:会对错误事件做出反应,而非下一步事件。