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
//cat
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");
}
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.
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 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).