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


当前回答

这里有一个警告。在Objective-C中,与许多类似的语言不同,您通常应该尽量避免在正常操作中可能发生的常见错误情况下使用异常。

Apple的Obj-C 2.0文档中写道:“重要的是:异常在Objective-C中是资源密集型的。您不应将异常用于一般的流控制,或仅用于表示错误(例如文件不可访问)”

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."

这样做的部分原因是坚持Objective-C中的编程习惯(在简单的情况下使用返回值,在更复杂的情况下使用按引用参数(通常是NSError类)),部分原因是抛出和捕获异常的代价要高得多,最后(可能是最重要的)Objective-C异常是C的setjmp()和longjmp()函数的一个瘦包装,本质上混乱了你仔细的内存处理,参见下面的解释。

其他回答

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

[NSException raise:@"Invalid foo value" format:@"foo of %d is invalid", foo];

这里有一个警告。在Objective-C中,与许多类似的语言不同,您通常应该尽量避免在正常操作中可能发生的常见错误情况下使用异常。

Apple的Obj-C 2.0文档中写道:“重要的是:异常在Objective-C中是资源密集型的。您不应将异常用于一般的流控制,或仅用于表示错误(例如文件不可访问)”

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."

这样做的部分原因是坚持Objective-C中的编程习惯(在简单的情况下使用返回值,在更复杂的情况下使用按引用参数(通常是NSError类)),部分原因是抛出和捕获异常的代价要高得多,最后(可能是最重要的)Objective-C异常是C的setjmp()和longjmp()函数的一个瘦包装,本质上混乱了你仔细的内存处理,参见下面的解释。

这是我从“大书呆子牧场指南(第四版)”中学到的:

@throw [NSException exceptionWithName:@"Something is not right exception"
                               reason:@"Can't perform this operation because of this or that"
                             userInfo:nil];

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

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

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

捕获异常 抛出异常

使用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).

参考链接:参考