throwing an exception in objective-c/cocoa

后端 未结 13 1622
耶瑟儿~
耶瑟儿~ 2020-11-29 15:01

What\'s the best way to throw an exception in objective-c/cocoa?

相关标签:
13条回答
  • 2020-11-29 15:14

    There is no reason not to use exceptions normally in objective C even to signify business rule exceptions. Apple can say use NSError who cares. Obj C has been around a long time and at one time ALL C++ documentation said the same thing. The reason it doesnt matter how expensive throwing and catching an exception is, is the lifetime of an exception is exceedingly short and...its an EXCEPTION to the normal flow. I have never heard anyone say ever in my life, man that exception took a long time to be thrown and caught.

    Also, there are people that think that objective C itself is too expensive and code in C or C++ instead. So saying always use NSError is ill-informed and paranoid.

    But the question of this thread hasnt yet been answered whats the BEST way to throw an exception. The ways to return NSError are obvious.

    So is it: [NSException raise:... @throw [[NSException alloc] initWithName.... or @throw [[MyCustomException... ?

    I use the checked/unchecked rule here slightly differently than above.

    The real difference between the (using the java metaphor here) checked/unchecked is important --> whether you can recover from the exception. And by recover I mean not just NOT crash.

    So I use custom exception classes with @throw for recoverable exceptions, because its likely I will have some app method looking for certain types of failures in multiple @catch blocks. For example if my app is an ATM machine, I would have a @catch block for the "WithdrawalRequestExceedsBalanceException".

    I use NSException:raise for runtime exceptions since I have no way to recover from the exception, except to catch it at a higher level and log it. And theres no point in creating a custom class for that.

    Anyway thats what I do, but if there's a better, similarly expressive way I would like to know as well. In my own code, since I stopped coding C a hella long time ago I never return an NSError even if I am passed one by an API.

    0 讨论(0)
  • 2020-11-29 15:18

    I think to be consistant it's nicer to use @throw with your own class that extends NSException. Then you use the same notations for try catch finally:

    @try {
    .....
    }
    @catch{
    ...
    }
    @finally{
    ...
    }
    

    Apple explains here how to throw and handle exceptions: Catching Exceptions Throwing Exceptions

    0 讨论(0)
  • 2020-11-29 15:22

    A word of caution here. In Objective-C, unlike many similar languages, you generally should try to avoid using exceptions for common error situations that may occur in normal operation.

    Apple's documentation for Obj-C 2.0 states the following: "Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)"

    Apple's conceptual Exception handling documentation explains the same, but with more words: "Important: You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime. [.....] Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the recommended way to communicate expected errors in Cocoa applications."

    The reasons for this is partly to adhere to programming idioms in Objective-C (using return values in simple cases and by-reference parameters (often the NSError class) in more complex cases), partly that throwing and catching exceptions is much more expensive and finally (and perpaps most importantly) that Objective-C exceptions are a thin wrapper around C's setjmp() and longjmp() functions, essentially messing up your careful memory handling, see this explanation.

    0 讨论(0)
  • 2020-11-29 15:22
    @throw([NSException exceptionWith…])
    

    Xcode recognizes @throw statements as function exit points, like return statements. Using the @throw syntax avoids erroneous "Control may reach end of non-void function" warnings that you may get from [NSException raise:…].

    Also, @throw can be used to throw objects that are not of class NSException.

    0 讨论(0)
  • 2020-11-29 15:23

    Regarding [NSException raise:format:]. For those coming from a Java background, you will recall that Java distinguishes between Exception and RuntimeException. Exception is a checked exception, and RuntimeException is unchecked. In particular, Java suggests using checked exceptions for "normal error conditions" and unchecked exceptions for "runtime errors caused by a programmer error." It seems that Objective-C exceptions should be used in the same places you would use an unchecked exception, and error code return values or NSError values are preferred in places where you would use a checked exception.

    0 讨论(0)
  • 2020-11-29 15:29

    You should only throw exceptions if you find yourself in a situation that indicates a programming error, and want to stop the application from running. Therefore, the best way to throw exceptions is using the NSAssert and NSParameterAssert macros, and making sure that NS_BLOCK_ASSERTIONS is not defined.

    0 讨论(0)
提交回复
热议问题