简体   繁体   中英

How to use sendError in ReactiveCocoa

I am new to reactive Cocoa and like it much that far.

I created a register page. If the username and password are valid I enable the register Button. For the login button I did the following:

[[[[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];
        }];

My Problem: if eg a username already exists I return an error. But If I return an error, then the subscription of rac_signalForControlEvents on the registerButton will end! I will get no more signals and my registerButton will not react anymore. And that is correct behavior according to the Documentation.

On the other hand: If I use sendNext instead of sendError in case of an error, I have different return types on sendNext (error or a dictionary with results in case of success). That is not nice too. So error is not usable in this case, since it does not allow an easy error handling.

What would be the correct reactive solution for that issue?

You can use catch: for that purpose.

[[[[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: works like as flattenMap: , but catch: reacts to error events, instead of next events.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM