在objective-c/cocoa中抛出异常的最佳方法是什么?


当前回答

使用NSError来传达失败而不是异常。

关于NSError的一些要点:

NSError allows for C style error codes (integers) to clearly identify the root cause and hopefully allow the error handler to overcome the error. You can wrap error codes from C libraries like SQLite in NSError instances very easily. NSError also has the benefit of being an object and offers a way to describe the error in more detail with its userInfo dictionary member. But best of all, NSError CANNOT be thrown so it encourages a more proactive approach to error handling, in contrast to other languages which simply throw the hot potato further and further up the call stack at which point it can only be reported to the user and not handled in any meaningful way (not if you believe in following OOP's biggest tenet of information hiding that is).

参考链接:参考

其他回答

我认为你永远不应该使用异常来控制正常的程序流程。但是,当某些值与所需值不匹配时,应该抛出异常。

例如,如果某个函数接受一个值,并且该值永远不允许为nil,那么就可以抛出一个异常,而不是尝试做一些“聪明”的事情……

Ries

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.

还有,有些人认为objective C本身太昂贵,而改用C或c++编写代码。所以说总是使用NSError是无知和偏执的。

但是这篇文章的问题还没有得到回答,抛出异常的最佳方式是什么。返回NSError的方法很明显。

[NSException raise:…]@throw [[NSException alloc] initWithName.... 或者@throw [[MyCustomException…]?

我在这里使用的选中/未选中规则与上面略有不同。

checked/unchecked之间的真正区别(此处使用java隐喻)非常重要——>您是否可以从异常中恢复。所谓恢复,我指的不仅仅是不崩溃。

所以我使用@throw的自定义异常类来处理可恢复的异常,因为 它可能会有一些应用程序的方法寻找某些类型的失败在多个 @catch块。例如,如果我的应用程序是一台ATM机,我将有一个@catch块用于 “WithdrawalRequestExceedsBalanceException”。

我使用NSException:raise用于运行时异常,因为我没有办法从异常中恢复, 除了在更高的级别捕获它并记录它。而且没有必要为此创建一个自定义类。

无论如何,这就是我所做的,但如果有更好的,类似的表达方式,我也想知道。在我自己的代码,因为我停止编码C海拉很久以前,我从来没有返回一个NSError,即使我通过一个API传递一个。

我使用[NSException raise:format:]如下所示:

[NSException raise:@"Invalid foo value" format:@"foo of %d is invalid", foo];
@throw([NSException exceptionWith…])

Xcode将@throw语句识别为函数出口点,就像return语句一样。使用@throw语法可以避免错误的“Control may reach end of non-void function”警告,你可能会从[NSException raise:…]得到这种警告。

同样,@throw也可以用来抛出不属于NSException类的对象。

我认为为了保持一致性,最好在你自己的类中使用@throw,它扩展了NSException。然后使用相同的表示法try catch finally:

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

Apple解释了如何抛出和处理异常:

捕获异常 抛出异常