StuartM
StuartM

Reputation: 6823

Using case switch instead of multiple if statements for error handling

I am building an application which has a login through a mobile SAAS - Parse.

There are multiple error codes that could be returned from a login request. At the moment run an if statement for each error code and display a relevant alert view like this:

        if (error == nil) {
            // Something went wrong
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"LoginAlertErrorTitle", @"Login Error Alert View Title") message:NSLocalizedString(@"LoginStandardError", @"Login error message text - standard error") delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"GlobalOKButtonTitle", @"Global Ok button title"), nil];
            [alertView show];
        } else  if ([error code] == kPFErrorObjectNotFound) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"LoginAlertErrorTitle", @"Login Error Alert View Title") message:NSLocalizedString(@"LoginErrorObjectNotFound", @"Login error message text - object not found") delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"GlobalOKButtonTitle", @"Global Ok button title"), nil];
            [alertView show];
        } else  if ([error code] == kPFErrorConnectionFailed) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"LoginAlertErrorTitle", @"Login Error Alert View Title") message:NSLocalizedString(@"LoginAlertErrorConnection", @"Login error message text - connection failed") delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"GlobalOKButtonTitle", @"Global Ok button title"), nil];
            [alertView show];
        } else {
            NSLog(@"A Login error occurred: %i",[error code]);
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"LoginAlertErrorTitle", @"Login Error Alert View Title") message:[[error userInfo] objectForKey:@"error"] delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"GlobalOKButtonTitle", @"Global Ok button title"), nil];
            [alertView show];
        }

Is there a more efficient way to do the same with case/switching?

The actual error codes are setup like this:

/*! @abstract 100: The connection to the Parse servers failed. */
extern NSInteger const kPFErrorConnectionFailed;

Which makes me think I can setup this in a case statement. Would this be the correct/best way to approach this? Should it be in a separate method like handleErrorAlert: possibly?

How would I code this switch in the example above?

Upvotes: 3

Views: 7787

Answers (3)

omz
omz

Reputation: 53561

Whether you use a switch statement or a series of if-else if is really just a matter of taste in this case. Yes, the switch statement is slightly more efficient, but in a case like this, it really doesn't matter (it's not like you call this thousands of times per second). Use what you find more readable.

You might want to refactor your alert view code a little though – you're doing the same thing in all cases with only the error message being different, so there's quite a bit of repeated code. You could refactor it like this:

NSString *errorMessage = nil;
if (error == nil) {
    errorMessage = NSLocalizedString(@"LoginStandardError", @"Login error message text - standard error");
} else {
     switch ([error code]) {
          case kPFErrorObjectNotFound:
               errorMessage = NSLocalizedString(@"LoginErrorObjectNotFound", @"Login error message text - object not found");
               break;
          case kPFErrorConnectionFailed:
               errorMessage = NSLocalizedString(@"LoginAlertErrorConnection", @"Login error message text - connection failed");
               break;
          default:
               errorMessage = [[error userInfo] objectForKey:@"error"];
     }
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"LoginAlertErrorTitle", @"Login Error Alert View Title") 
                                                    message:errorMessage
                                                   delegate:self
                                          cancelButtonTitle:nil
                                          otherButtonTitles:NSLocalizedString(@"GlobalOKButtonTitle", @"Global Ok button title"), nil];
[alertView show];

Upvotes: 10

Constantino Tsarouhas
Constantino Tsarouhas

Reputation: 6886

if (!error) {
    // Handle error (?).
}

switch ([error code]) {
    case kPFErrorObjectNotFound:
        // Handle error.
        break;
    case kPFErrorConnectionFailed:
        // Handle error.
        break;
    default:
        // Handle error.
}

This only works if the value returned by -code can be used in a switch test expression. AFAIK, int is supported—I don't know about other types.

Upvotes: 1

Rui Peres
Rui Peres

Reputation: 25917

A typedef enum being used on a switch, I think it would be the cleanest way. Something like this:

typedef enum
{
kServerError,
kInternetError,
kUnknowError
} kTypeError;

switch (aTypeError)
{
.
.
.
}

In your specific case, you take care about the message inside the switch... The UIAlertView is a common part. So:

NSString *aTitle = nil;
NSString *aMessage = nil;

switch (aTypeError)
{
    case kUnknowError:
    {
        aTitle = ...;
        aMessage = ...;
    }
    break;
}

UIAlertView *alertView = [UIAlertView alloc] ...

Upvotes: 4

Related Questions