Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C - Catch exception raised from inside a block

I'm using the following code in app:

@try {
        if(!self.usernameField.text || [self.usernameField.text isEqualToString:@""])
            [NSException raise:@"Invalid value for username" format:@"Please enter your username."];

        if(!self.passwordField.text || [self.passwordField.text isEqualToString:@""])
            [NSException raise:@"Invalid value for password" format:@"Please enter your password."];


        [LoginManager
         userLogin:self.usernameField.text
         andPassword:self.passwordField.text
         success:^(AFHTTPRequestOperation *op, id response) {

             if([self.delegate respondsToSelector:@selector(loginSuccessWithUserName:)]) {
                 [self.delegate performSelector:@selector(loginSuccessWithUserName:)withObject:self.usernameField.text];
             }

             [self dismissPopoverController];
         }
         failure:^(AFHTTPRequestOperation *op, NSError *err) {
             NSString* nsLocalizedRecoverySuggestion = [err.userInfo objectForKey:@"NSLocalizedRecoverySuggestion"];

             if(err.code == -1009) {

                 [NSException raise:@"No Internet connection" format:@"It appears you’re not connected to the internet, please configure connectivity."];
             }

             if([nsLocalizedRecoverySuggestion rangeOfString:@"Wrong username or password."].location != NSNotFound) {

                 [NSException raise:@"Invalid username or password" format:@"Your given username or password is incorrect"];
             }
             else {
                 [NSException raise:@"BSXLoginViewController" format:@"Error during login"];
             }
         }];
    }
    @catch (NSException *exception) {
        UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Login error"
                                                       message:exception.description
                                                      delegate:self
                                             cancelButtonTitle:@"Ok"
                                             otherButtonTitles:nil];
        [alert show];
    }

However the exceptions raised in the failure block don't get catched in the catch section. I kind of understand why it's logical, but i would like to know if there's a way to tell the block that the exceptions happening inside should be handled by the catch section i created.

Thanks for any help!

Sincerely, Zoli

like image 845
Zoltan Varadi Avatar asked Nov 17 '25 10:11

Zoltan Varadi


2 Answers

Don't do this. First of all, and I'm sure you'll get at least a comment from @bbum about this, NSException isn't intended in Objective-C for recoverable errors and propagating recoverable errors through code (see Introduction to Exception Programming Topics for Cocoa). Instead, the construct used in Objective-C is to use NSException basically for unrecoverable programming errors, and to use NSError objects for handing around recoverable errors.

However, you've got a bigger problem here in that the calls that you are making have block callbacks because they return before completing. In this case, your exception handler is exited long before the exceptions are actually thrown.

In this case, I'd suggest removing the exceptions and handling the errors inside of the actual failure: block by dispatching to the main queue and presenting the UIAlert there.

like image 162
gaige Avatar answered Nov 18 '25 23:11

gaige


Don't be fooled by the fact that your block is specified inline with other code. You cannot catch exceptions in the block in the outer (non-block) code because the code in the TRY block has already executed (and exited) and the block only executes in it's own scope.

A solution is to catch exceptions in the block.

like image 28
Blaine Murray Avatar answered Nov 19 '25 00:11

Blaine Murray



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!