Try-catch exception handling practice for iPhone/Objective-C
如果这个问题已经在其他地方得到了回答,我深表歉意,但我在搜索时找不到任何决定性的答案:
我想知道何时在Objective-C iPhone应用程序中使用Try-Catch块。苹果公司的"Objective-C编程语言简介"指出,异常是资源密集型的,并且"不应该将异常用于一般的流控制,或者仅仅是表示错误。"从阅读这里的几个相关问题中,我还得出结论,人们在实践中并不经常使用这种方法。
所以我想问题是:在为iPhone/Objective-C开发时,使用Try-Catch块是合适的,什么时候绝对不应该使用它们?
例如,在处理数组中的对象时,我可以使用它们来捕获越界和其他异常。我有一个方法,它使用在许多数组中传递的对象来执行很少的任务。如果发生错误,并且try catch块可以帮助捕获异常,则该方法返回nil。但是,我当然可以在这里或那里编写很少的if测试,以确保我,例如,从未尝试访问数组边界之外的索引。在这种情况下你会怎么做?
谢谢!
- 接受任何一个答案……或者发表你自己的答案……超过1万名游客仍然困惑。
- 有关最佳实践,请参阅完整答案stackoverflow.com/a/6802326/1845634。
只适合使用@try/@catch来处理不可恢复的错误。使用@throw/@try/@catch来控制类似流的操作是不合适的。
特别是,除非您的目标是捕获越界异常并以某种方式报告错误,否则不适合用于捕获越界异常,然后——通常——崩溃,或者至少警告用户您的应用程序处于不一致状态,可能会丢失数据。
通过系统框架代码引发的任何异常的行为都是未定义的。
您的if-test-to-do-bounds检查是一个更合适的解决方案。
@bbum的回答是绝对正确的(而且他比大多数人都知道答案)。详细说明一下……
在cocoa中,通常应该避免使用异常(@try/@catch[/@finally]来控制流。正如您所提到的,异常具有异常大的成本(与运行时(如jvm或为异常使用而优化的clr)相比)。此外,大多数Cocoa框架都是非常安全的。因此,通过Cocoa框架代码抛出异常是危险的,可能会导致应用程序中出现奇怪的、难以诊断的以及灾难性的(认为可能的数据丢失)错误。
Cocoa代码不使用异常,而是使用NSError来表示应用程序中可恢复的错误条件。异常用于指示应用程序无法从中恢复的条件。因此,请求模型数组中越界位置的UI组件在尝试访问越界位置时可能会发出错误信号(向用户显示,并说明其请求无法完成的原因),同时给出一个您认为应该有效的索引,表示您的应用程序处于不一致的异常情况。在它造成更多伤害之前,应该尽快死亡。
NSParameterAssert,例如,当断言失败时,用NSException发出信号。
那么,什么时候应该使用异常或@try/@catch?如果您使用的是使用异常的C/C++库,则在捕获COCOA代码之前,您应该捕获这些异常。同样,如果您认真对待应用程序中状态的一致性,则应该在检测到状态不一致(并且不可恢复)时立即引发异常。
- 比你的扩张更重要。还要注意,断言和abort()是您的朋友;它们会导致应用程序在失败时崩溃。当你@throw时,你必须努力重建应用程序在检测到异常时的确切位置。及早失败。努力失败。
- 我不知道NSerror是Java样式的Test/catch结构的一个很好的替代品。整个想法是,您不需要为了处理错误而把下游的所有代码都搞乱。使用nserrror似乎需要传递可能引发错误的所有方法。丑陋且容易出错。在某些情况下,使用nsexceptions进行黑客攻击可能是一件好事。是的,很明显例外只适用于例外情况,而不适用于正常的预期情况。
- 实际上,异常仅限于当前线程的堆栈。当您@throw时,您将转到上面的任意帧(带有@catch或@finally的帧)。因此,即使在遇到类似gc的情况下,要求在任何地方实现的每个方法都必须始终为该框架内的任何语句做好准备,使其成为最后执行的语句(或者每个方法都必须实现@finally)。最终的结果是大量的脆弱性、低效性和代码大小的增加。它也与objc的活力背道而驰。
- 不要说基于异常的系统在从一开始就为其设计的语言和API中是不可行的,只是这其中也有很多成本。nserrror也不是很好,但它保留了可预测的线性执行路径。
- 当您捕获所有断点(stackoverflow.com/a/14371689/412916)时,Xcode中的私有异常也很烦人。我想知道在核心数据框架中使用它们的基本原理是什么。