I am working on porting a Java codebase to Cocoa/Objective-C for use on desktop Mac OS X. The Java code has lots and lots of methods with checked exceptions like:
double asNumber() throws FooException {
...
}
What’s the best way to represent these in Objective-C? Exceptions or error out-parameters?
- (CGFloat)asNumber {
... // possibly [FooException raise:format:];
}
or
- (CGFloat)asNumberError:(NSError **)outError {
...
}
I have the sense that out-errors are generally the better solution for Objective-C, but as you can see… a lot of methods like the one above will be quite awkward-looking. And again, there are lots of these.
Of course keep in mind that since these are checked exceptions in Java, I will need to add either @try blocks or if (*outError) {...} checks wherever these methods are called (lots of places).
I recall hearing that while entering @try blocks was once expensive in Objective-C, it is cheap in 64-bit or SL or some other new env (don’t recall exactly). I am not at all concerned about backwards compatibility, so i am definitely willing to design only for the new hotness.
You should definitely avoid exceptions for things like parsing numbers from strings. In Objective-C, exceptions represent programmer error, not user input error, or even unavailable files. (Part of the reason is that exception handling is always more costly and complex than more “conventional” error handling. Regardless of the fact that entering
@tryblocks is “zero cost” in 64-bit, it’s still slow whenever an exception is actually raised.) Of course, you’re allowed to use exceptions as you like, but it’s not the Cocoa way, and you’ll find yourself at odds with other Objective-C code. People who use your code will be incredibly annoyed that you throw exceptions in cases that should just result in an error.From Apple’s own docs:
Look at how built-in Cocoa classes handle errors like this. For example, NSString has methods like
-floatValuethat return 0 if it fails. A better solution for your particular situation might be how NSScanner does it, such as in-scanFloat:— accept a pointer to the field where the result should be stored, and returnYESorNObased on whether the parse was successful.Aside from Obejctive-C convention and best practices, NSError is much more robust and flexibly than NSException, and allows the caller to effectively ignore the problem if they want to. I suggest reading through the Error Handling Programming Guide For Cocoa. Note: If you accept an
NSError**param, I strongly suggest you also design to allow the client to passNULLif they don’t want to receive any error information. Every Cocoa class I’m aware of does this for errors, including NSString.Although the ported code may end up looking totally different from the Java code, recognize that it will be used by Objective-C code, not the same clients of the Java equivalent. Definitely match the idioms of the language. The port will not be a mirror image of the Java code, but it will be much more correct (for Objective-C) as a result.