7

I am trying to achieve something like this in objective c.

@try{
//some code that will raise exception
}
@catch(CustomException e){//How to create this
//catching mechanism
}
@catch(NSException e){
//Generic catch
}

I need to create CustomException class and use it. Could you please help me in creating this CustomException and guide me in how to use this.

Thanks in advance.

Easwaramoorthy Kanagaraj
  • 3,925
  • 8
  • 36
  • 62

2 Answers2

28

Exceptions are very rarely used for control flow like this in Objective-C. I'm guessing you have a Java (or similar) background.

I'm not saying that you can't write code like this but it will feel very strange for other people looking at your code and could also possibly work badly if used by other peoples code if you don't completely isolate the exceptions so that it never reaches their code.

How it is commonly done in Objective-C

Exceptions are used for critical errors. If the error is expected (like it seems to be since you want to @try it) you should instead try and return an NSError. This is a design pattern that is used all over the Foundation and Cocoa frameworks and also third party frameworks. Look for example at networking, file reading/writing or JSON code (JSONObjectWithData:options:error:)

What you would do

What you do is add a error parameter (double pointer) at the end of your method that could fail, like this:

- (MyResultObject *)myMethodThatCouldFailWith:(MyObject *)myObject
                                        error:(NSError **)error;

When someone (you or someone else) uses this method they can if they want to pass a NSError pointer that will get set if an error occurred, like this:

NSError *error = nil; // Assume no error
MyResultObject *result = [self myMethodThatCouldFailWith:myObject
                                                   error:&error];
if (!result) {
    // An error occurred, you can check the error object for more information.
}

Note the ampersand (&) before the error parameter. This means that you are sending your error points as the argument so that inside the risky method that pointer can be changed to points to a new NSError object which can be read after the method returns.

Now, inside your method that could fail, you would set the error to a new NSError object if something went wrong (instead of raising an exception). It is also very common to return nil when an error occurs since that probably means that the calculation won't be able to complete or that the data is unreliable or irrelevant.

- (MyResultObject *)myMethodThatCouldFailWith:(MyObject *)myObject
                                        error:(NSError **)error {
    // Do something "risky" ...
    MyResultObject *result = [MyResultObject somethingRiskyWith:myObject];
    
    // Determine if things went wrong
    if (!result) {
        // Set error if a pointer for the error was given 
        if (error != NULL) {
            *error = [NSError errorWithDomain:yourErrorDomain
                                         code:yourErrorCode
                                     userInfo:optionalDictionaryOfExtraInfo];
        }
        return nil;
    }
    
    // Everything went fine.
    return result;
}

Now if the error returns you can identify what kind of error it was from the error code that you specified and you can read more detailed information in the user info dictionary (where you can add lots of information).

Community
  • 1
  • 1
David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
15

In the simplest case, I can declare a class using...

@interface CustomException : NSException
@end
@implementation CustomException
@end

...and the code is very much like what you posted:

   @try{
        @throw [[CustomException alloc] initWithName:@"Custom" reason:@"Testing" userInfo:nil];
    }
    @catch(CustomException *ce){
        NSLog(@"Caught custom exception");
    }
    @catch(NSException *e){
        NSLog(@"Caught generic exception");
    }
Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • Thanks Phillip. In java we can give the error message in the subclass of Exception itself. Can we do that here? Just comparing this with java. Could you please explain? – Easwaramoorthy Kanagaraj Jul 15 '12 at 16:09
  • 1
    Two possibilities come to mind: the `reason` in the init method is a string that can be referenced, displayed, compared...by whatever catches it, and, since it's a custom class it can define any of its own properties or methods that you need. – Phillip Mills Jul 15 '12 at 16:33
  • Use NSErrors, as recommended by Apple. You may include a custom message in the UserInfo dict. – emma ray Dec 01 '14 at 17:05