iOS中的异常处理

7
阅读文档并查看苹果示例代码(以及大部分第三方Objective-C代码),我得出的印象是,不应该使用try/catch和“传统/C”方法来处理异常。
最近我在阅读亚马逊AWS iOS SDK时发现,他们频繁地使用了旧方法。
这让我感到宽慰,因为我一直觉得当我使用其他人编写的代码或二进制库(例如Google Analytics二进制文件)时,我需要确保自己捕获异常。
我的问题是,是否有任何理由避免在iOS上进行“传统”的异常处理,或者仅仅是因为这不是一种优雅的Objective-C实践?

4
嗯,try/catch不是处理错误的“传统C语言”方法。 - Perception
1
传统的 C 错误处理方法是返回 NULL 或 -1 来表示错误,并设置全局 errno。另一种常用技术是直接返回错误代码,其中一个可能的错误是 SUCCESS、NO_ERROR 或类似的内容。C 没有直接支持异常处理的语言支持。setjmplongjmp 提供了实现它们的工具,但这不像在 C++ 中那样是一种语言特性。 - Rob Napier
2个回答

11

有充分的理由要避免在iOS上使用异常。

iOS上的异常专门用于无法恢复的灾难性故障,不适用于捕获和恢复类型的操作。

重要提示:应将异常保留用于编程或意外的运行时错误,例如越界访问集合、尝试更改不可变对象、发送无效消息和失去与窗口服务器的连接。通常在创建应用程序时就使用异常来处理这些类型的错误,而不是在运行时处理。

如果您有现有的代码库(例如第三方库)使用异常来处理错误条件,则可以在Cocoa应用程序中使用该代码库。但是,您应确保任何预期的运行时异常不会从这些子系统逃逸并进入调用者的代码。例如,解析库可能在内部使用异常来指示问题,并启用可以深度递归的解析状态的快速退出;但是,您应确保在库的顶层捕获此类异常,并将其转换为适当的返回代码或状态。

这导致了两个问题(其中之一):

  • 在系统框架代码的帧中,您无法通过@throw抛出异常。 行为未定义。

  • 如果您设计代码使用异常,那么您的代码和系统之间的边界将存在巨大的阻抗不匹配。不仅这很尴尬,而且随着边界的移动,所有未来的维护和重构操作都将更加困难。 这还将使与系统集成更加困难。

请注意,如果AWS SDK通过由系统框架拥有的堆栈帧抛出异常,则说明它做错了。


1
好的,但它们是否是可恢复的错误?如果是,就不应该使用异常。如果它们是无法恢复的异常,用于退出应用程序(最好附带崩溃报告),那就没问题了。 - bbum
1
你必须在你的代码和第三方API之间的边界处捕获异常,然后相应地进行处理。如果该库直接调用系统代码传递异常,那么该库就是有问题的。 - bbum
如果我对以下链接的理解是正确的,那么iOS异常周围存在着很多不必要的恐惧。http://club15cc.com/code/objective-c/dispelling-nsexception-myths-in-ios-can-we-use-try-catch-finally - occulus
但是一定要阅读博客文章的评论,它们也非常有启发性。 - occulus
我一段时间前在我的博客文章中发表了评论和更详细的信息:http://orangejuiceliberationfront.com/why-cocoa-programmers-cant-have-nice-things/ 对于不仅仅是技术上,而且是实用的观点来说,在ObjC中使用异常目前并不是很有用。 - uliwitness
显示剩余3条评论

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接