ede*_*y05 10 exception objective-c nsoperation
在Apple的并发编程指南中,NSOperation子类示例(非并发和并发变量)使用异常处理,我想知道为什么他们在操作中鼓励这种风格.
清单2-4响应取消请求
- (void)main {
@try {
BOOL isDone = NO;
while (![self isCancelled] && !isDone) {
// Do some work and set isDone to YES when finished
}
}
@catch(...) {
// Do not rethrow exceptions.
}
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,通常异常处理不是Objective-C代码中的常见做法 - 异常本质上是程序员错误,应该导致应用程序崩溃,而意外输入最好由NSError处理.(我可能误导理解来自之类的东西这个和这个)
我想知道NSOperations是否存在特殊情况,其中异常处理很重要,或者这是否是该指南的特定作者的首选样式.
作为旁注,一些NSOperation示例代码遵循此样式,其他示例则不遵循此样式.大多数高可见性OSS不使用例外(例如AFNetworking).
您的理解是正确的 - 应该使用NSError(或类似)来传达错误信息,而不是异常.大多数Objective-C代码都不是异常安全的,至少会泄漏资源.作为一般规则,永远不要让您的代码泄露任何其他人的代码 - 无论是苹果公司还是第三方.一些第三方框架可能明确表明它们是异常安全的,但它很少见.
根据这个原则,你可以看到为什么你的方法中应该有一个catch-all异常处理程序main.但实际上还有另一个原因:您的操作将在专用线程上运行.从您的操作中抛出的异常将在堆栈中向上传播,但不会再进一步.操作的逻辑调用者或所有者将不会获取它们,因为它们在不同的线程上运行(或根本不运行).因此,泄露的异常会杀死整个程序,或者在没有其他指示的情况下静默吞咽.您的程序可能会陷入一种奇怪的状态 - 因为您没有意识到发生了错误,您可能会继续等待您的操作结果永远不会到达.
此外,Apple在" 并发编程指南"中有一节介绍处理错误和异常.他们关于"离散实体"的第一点是暗示我在前一段中所说的:
处理错误和例外
由于操作本质上是应用程序内的离散实体,因此它们负责处理出现的任何错误或异常.在OS X v10.6及更高版本中,NSOperation类提供的默认启动方法不会捕获异常.(在OS X v10.5中,start方法会捕获并抑制异常.)您自己的代码应始终直接捕获和抑制异常.它还应检查错误代码并根据需要通知应用程序的相应部分.如果替换start方法,则必须同样捕获自定义实现中的任何异常,以防止它们离开底层线程的范围.
您应该准备处理的错误情况类型如下:
- 检查并处理UNIX errno样式的错误代码.
- 检查方法和函数返回的显式错误代码.
- 捕获您自己的代码或其他系统框架抛出的异常.
- 捕获NSOperation类本身抛出的异常,它会在以下情况下抛出异常:
- 当操作未准备好执行但调用其start方法时
- 当操作正在执行或完成时(可能因为它被取消)并且再次调用其start方法
- 当您尝试将完成块添加到已执行或已完成的操作时
- 当您尝试检索已取消的NSInvocationOperation对象的结果时
如果您的自定义代码确实遇到异常或错误,则应采取将该错误传播到应用程序其余部分所需的任何步骤.NSOperation类不提供将错误结果代码或异常传递给应用程序其他部分的显式方法.因此,如果此类信息对您的应用程序很重要,则必须提供必要的代码.