避免抛异常
Tip
不要 @throw
Objective-C 异常,同时也要时刻准备捕获从第三方或 OS 代码中抛出的异常。
我们的确允许 -fobjc-exceptions
编译开关(主要因为我们要用到 @synchronized
),但我们不使用 @throw
。为了合理使用第三方的代码,@try
、@catch
和 @finally
是允许的。如果你确实使用了异常,请明确注释你期望什么方法抛出异常。
不要使用 NS_DURING
、NS_HANDLER
、NS_ENDHANDLER
、NS_VALUERETURN
和 NS_VOIDRETURN
宏,除非你写的代码需要在 Mac OS X 10.2 或之前的操作系统中运行。
注意:如果抛出 Objective-C 异常,Objective-C++ 代码中基于栈的对象不会被销毁。比如:
- class exceptiontest {
- public:
- exceptiontest() { NSLog(@"Created"); }
- ~exceptiontest() { NSLog(@"Destroyed"); }
- };
- void foo() {
- exceptiontest a;
- NSException *exception = [NSException exceptionWithName:@"foo"
- reason:@"bar"
- userInfo:nil];
- @throw exception;
- }
- int main(int argc, char *argv[]) {
- GMAutoreleasePool pool;
- @try {
- foo();
- }
- @catch(NSException *ex) {
- NSLog(@"exception raised");
- }
- return 0;
- }
会输出:
注意:这里析构函数从未被调用。这主要会影响基于栈的 smartptr
,比如 shared_ptr
、linked_ptr
,以及所有你可能用到的 STL 对象。因此我们不得不痛苦的说,如果必须在 Objective-C++ 中使用异常,就只用 C++ 的异常机制。永远不应该重新抛出 Objective-C 异常,也不应该在 @try
、@catch
或 @finally
语句块中使用基于栈的 C++ 对象。