Try-catch exception handling practice for iPhone/Objective-C

12,488

Solution 1

It is only appropriate to use @try/@catch to deal with unrecoverable errors. It is never appropriate to use @throw/@try/@catch to do control-flow like operations.

In particular, it would not be appropriate to use for catching out-of-bounds exceptions unless your goal is to catch them and somehow report the error, then -- typically -- crash or, at the least, warn the user that your app is in an inconsistent state and may lose data.

Behavior of any exception thrown through system framework code is undefined.

Your if-test to do bounds checking is a far more appropriate solution.

Solution 2

@bbum's answer is absolutely correct (and he would know the answer better than most). To elaborate a bit...

In Cocoa, you should generally avoid using exceptions (@try/@catch[/@finally]) for flow control. As you mention, exceptions carry an unusually large cost (compared to run-times such as JVM or the CLR optimized for exception use). Furthermore, most of the Cocoa frameworks are not exception safe. Thus, throwing an exception through Cocoa framework code is dangerous and will likely cause odd, difficult to diagnose, and catastrophic (think possible data loss) bugs in your app.

Instead of using exceptions, Cocoa code uses NSError to signal error conditions that are recoverable within the application. Exceptions are used to signal conditions from which your application cannot recover. Thus a UI component requesting an out-of-bounds position in a model array could be signaled with an error (presented to the user with a reason their request could not be completed) while attempting to access an out-of-bounds position given an index that you think should be valid signals an exceptional condition where you app is in an inconsistent state and should probably die as soon as possible before it can do more damage.

NSParameterAssert, for example signals with an NSException when an assertion fails.

So when should you use exceptions or @try/@catch? If you're using a C/C++ library that makes use of exceptions, you should catch those exceptions before they can get thrown back through Cocoa code. Similarly, if you are serious about consistency of state within your application, you should raise an exception as soon as you detect that your state is inconsistent (and unrecoverable).

Share:
12,488

Related videos on Youtube

Ansig
Author by

Ansig

Updated on February 11, 2020

Comments

  • Ansig
    Ansig about 4 years

    Apologies if this question has already been answered somewhere else, but I could not find any decisive answer when searching on it:

    I'm wondering when try-catch blocks are to be used in objective-c iPhone applications. Apple's "Introduction to the Objective-C Programming Language" state that exceptions are resource intensive and that one should "not use exceptions for general flow-control, or simply to signify errors." From reading a few related questions here I also gather that people are not often using this method in practice.

    So I guess the question is: what are the situations when it's appropriate to use try-catch blocks when developing for iPhone/Objective-C and when should they absolutely NOT be used?

    For example, I could use them to catch beyond bounds and other exceptions when working with objects in arrays. I have a method which performs are few tasks with objects that are passed on in a number of arrays. The method returns nil if an error has occurred and a try-catch block could help me catch exceptions. However, I could of course simply write little if-tests here and there to ensure that I, for instance, never try to access an index beyond an arrays bounds. What would you do in this situation?

    Thanks a lot!

    • Ranjithkumar
      Ranjithkumar about 9 years
      accept any one answer..else post your own answer..More than 10k visitors still confused.
    • dazzli
      dazzli about 9 years
      See this complete answer stackoverflow.com/a/6802326/1845634 for best practices.
  • bbum
    bbum over 13 years
    Than you for the expansion. Note also that asserts and abort() are your friend; they cause the app to crash at the point of failure. When you @throw, you have to work hard to reconstruct exactly where the app was at the time the anomaly was detected. Fail early. Fail hard.
  • n13
    n13 almost 12 years
    I don't see how NSError is a good replacement for a Java style try/catch structure. The whole idea is that you don't need to mess up all the code downstream just to handle an error. Using NSError seems to entail passing it down any and all methods that might raise an error. Ugly and error-prone. Hacking it with NSExceptions might be a good thing to under certain circumstances. And yeah clearly exceptions are only for the exceptional case, not for normal, expected things.
  • bbum
    bbum almost 12 years
    Exceptions are, effectively, a GOTO limited to the stack of the current thread. When you @ throw, you GOTO some arbitrary frame above (the one with the @catch or @ finally). Thus, the requirement is very much -- even in the face of something like GC -- that every method ever implemented anywhere must always be prepared for any statement within that frame to be the last statement executed (or every method must implement an @ finally). The end result is mass fragility, inefficiency and an increase in code size. It also flies in the face of ObjC's dynamism.
  • bbum
    bbum almost 12 years
    Not to say that an exception based system isn't viable in languages and APIs that design for it from the start, just that there is a lot of cost there, too. NSError isn't exactly awesome, either, but it preserves the predictable, linear, execution path.
  • Jano
    Jano almost 11 years
    Private exceptions are also annoying in Xcode when you are catching all breakpoints (stackoverflow.com/a/14371689/412916). I wonder what was the rationale of using them in the Core Data framework.