在objective-c/cocoa中抛出异常的最佳方法是什么?
我使用[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的概念异常处理文档解释相同,但更多的话:"重要:您应该保留使用异常编程或意外的运行时错误,例如越界集合访问,尝试改变不可变对象,发送无效消息并且失去了与窗口服务器的连接.在创建应用程序时而不是在运行时,通常会处理这些类型的错误和异常.[......]而不是异常,错误对象(NSError)和Cocoa错误传递机制是在Cocoa应用程序中传达预期错误的推荐方法."
其原因部分是为了坚持Objective-C中的编程习惯用法(在更复杂的情况下使用简单情况下的返回值和引用参数(通常是NSError类)),部分原因是抛出和捕获异常要贵得多,最后(并且最重要的是),Objective-C异常是C的setjmp()和longjmp()函数的一个薄包装,基本上搞乱了你仔细的内存处理,请参阅这个解释.
@throw([NSException exceptionWith…])
我没有代表对eJames的回应发表评论,所以我想我需要把它放在这里.对于那些来自Java背景的人,您会记得Java区分Exception和RuntimeException.异常是已检查的异常,并且未选中RuntimeException.特别是,Java建议使用"正常错误条件"的已检查异常和"由程序员错误导致的运行时错误"的未经检查的异常.似乎应该在使用未经检查的异常的相同位置使用Objective-C异常,并且在使用已检查异常的位置首选错误代码返回值或NSError值.
我认为是一致的,使用@throw与你自己的类扩展NSException更好.然后你最后使用相同的符号来try catch:
@try { ..... } @catch{ ... } @finally{ ... }
Apple在这里解释了如何抛出和处理异常: 捕获异常 抛出异常
从ObjC 2.0开始,Objective-C异常不再是C的setjmp()longjmp()的包装器,并且与C++异常兼容,@ try是"免费的",但抛出和捕获异常的方式更加昂贵.
无论如何,断言(使用NSAssert和NSCAssert宏系列)抛出NSException,并且理所当然地将它们用作Ries状态.
使用NSError来传达故障而不是异常.
关于NSError的快速点:
NSError允许C样式错误代码(整数)清楚地标识根本原因,并希望允许错误处理程序克服错误.您可以非常轻松地在NSError实例中包含SQL库(如SQLite)中的错误代码.
NSError还具有作为对象的优点,并提供了一种使用其userInfo字典成员更详细地描述错误的方法.
但最重要的是,不能抛出NSError,因此它鼓励采用更主动的错误处理方法,与其他语言相比,这些语言只是将热门土豆进一步向上调整堆栈,此时它只能报告给用户和没有以任何有意义的方式处理(如果你相信遵守OOP隐藏的最大信息原则).
参考链接: 参考
这就是我从"The Big Nerd Ranch Guide(第4版)"中学到的:
@throw [NSException exceptionWithName:@"Something is not right exception" reason:@"Can't perform this operation because of this or that" userInfo:nil];
您可以使用两种方法在try catch块中引发异常
@throw[NSException exceptionWithName];
或第二种方法
NSException e; [e raise];