避免抛异常

Tip

不要 @throw Objective-C 异常,同时也要时刻准备捕获从第三方或 OS 代码中抛出的异常。

我们的确允许 -fobjc-exceptions 编译开关(主要因为我们要用到 @synchronized ),但我们不使用 @throw。为了合理使用第三方的代码,@try@catch@finally 是允许的。如果你确实使用了异常,请明确注释你期望什么方法抛出异常。

不要使用 NS_DURINGNS_HANDLERNS_ENDHANDLERNS_VALUERETURNNS_VOIDRETURN 宏,除非你写的代码需要在 Mac OS X 10.2 或之前的操作系统中运行。

注意:如果抛出 Objective-C 异常,Objective-C++ 代码中基于栈的对象不会被销毁。比如:

  1. class exceptiontest {
  2. public:
  3. exceptiontest() { NSLog(@"Created"); }
  4. ~exceptiontest() { NSLog(@"Destroyed"); }
  5. };
  6.  
  7. void foo() {
  8. exceptiontest a;
  9. NSException *exception = [NSException exceptionWithName:@"foo"
  10. reason:@"bar"
  11. userInfo:nil];
  12. @throw exception;
  13. }
  14.  
  15. int main(int argc, char *argv[]) {
  16. GMAutoreleasePool pool;
  17. @try {
  18. foo();
  19. }
  20. @catch(NSException *ex) {
  21. NSLog(@"exception raised");
  22. }
  23. return 0;
  24. }

会输出:

注意:这里析构函数从未被调用。这主要会影响基于栈的 smartptr,比如 shared_ptrlinked_ptr,以及所有你可能用到的 STL 对象。因此我们不得不痛苦的说,如果必须在 Objective-C++ 中使用异常,就只用 C++ 的异常机制。永远不应该重新抛出 Objective-C 异常,也不应该在 @try@catch@finally 语句块中使用基于栈的 C++ 对象。