整个应用程序中的exception处理

我对iPhone中的exception处理有一些怀疑。 他们是:

  1. 假设我有一个接一个被调用的方法链,也就是方法A调用方法B,方法B又调用方法C,调用方法D.哪一个放置我的try-catch块是最好的地方是方法A还是B还是C或D还是全部)。 此外,我需要显示一个警告给用户,发生exception,然后,我想logging这个exception到我的服务器。 所以,如果我在所有这些方法中写入try-catch块,并且在方法D中发生exception, 那么我认为这个alert会显示4次,logging的web服务也会被调用4次(直到控件到达方法A的catch块)。 所以,我应该只使用@throw; 在方法B,C和D的catch块中,在方法A的catch块中写入我的逻辑(顶层方法),还是应该避免在方法B,C和D中写入try-catch。

  2. 我需要一些来自exception的错误代码(因为我的Web服务需要参数错误代码和描述)。 是否有可能将exception转换为错误,或者是否需要对此代码进行硬编码?

  3. 我曾经读过关于NSSetUncaughtExceptionHandler的地方。 我认为,如果我可以设置此处理程序(在应用程序委托的appDidFinishLaunching方法中)和处理程序方法中,如果我向用户显示一些警报并调用Web服务; 那么我不需要在每个类的每个方法中都写try – catch块。 我对吗??

  4. 如果发生exception,而且我写了try-catch块或NSSetUncaughtExceptionHandler,那么我的应用程序将继续运行,否则它将不会响应任何用户事件。 (我相信它会处理崩溃,我想知道的是它是否会挂起)

有人请赐教我这个例外的主题。

0)避免cocoa中的exception。 它们通常是不可恢复的。 你可能会为了自己的错误报告而抓到他们,但是假设你可以从中恢复,通常是不安全的。

1)如果你需要赶上, 立即抓住它。 不要编写自己的throws ,而应该把它转换成类似于NSError东西,然后传递给它。 NSError可以包含所有需要显示或发送错误代码以及本地化消息的信息。

2)你不能将NSException (直接)转换成NSError因为NSException不具有NSError具有的所有属性 – 它是一种不同的数据表示forms。 首先,错误代码不可用。 二,描述不是本地化的。 你可以做的最好的是创build一个错误代码和域,然后使用NSException需要的属性,并将其存储在NSError 。 这可能看起来像下面这样:

 // error checking omitted extern NSString* const MONExceptionHandlerDomain; extern const int MONNSExceptionEncounteredErrorCode; NSError * NewNSErrorFromException(NSException * exc) { NSMutableDictionary * info = [NSMutableDictionary dictionary]; [info setValue:exc.name forKey:@"MONExceptionName"]; [info setValue:exc.reason forKey:@"MONExceptionReason"]; [info setValue:exc.callStackReturnAddresses forKey:@"MONExceptionCallStackReturnAddresses"]; [info setValue:exc.callStackSymbols forKey:@"MONExceptionCallStackSymbols"]; [info setValue:exc.userInfo forKey:@"MONExceptionUserInfo"]; return [[NSError alloc] initWithDomain:MONExceptionHandlerDomain code:MONNSExceptionEncounteredErrorCode userInfo:info]; } @catch (NSException * exc) { NSError * err = NewNSErrorFromException(exc); ... } 

如果你使用的API抛出exception,你会被捕获并从中恢复(例如,不是真正的例外情况),那么是的,你可以捕获并尝试继续。 不幸的是,任何在Cocoa中编写exception的人都想要抓住它们,可能对于实现一个可靠的展开实现(例如,即使产生泄漏并不稳定)也不了解。

3)这不是显示警报的时间或地点。 如果你安装了一个顶级的exception处理程序(通过NSSetUncaughtExceptionHandler ) – 你应该简单地logging一条消息,然后exception处理程序将中止。 你的应用程序处于不稳定的状态 – 继续比放弃更糟糕。 您可能希望将这些自定义消息发送回家,下次启动应用程序时最好这样做。

4)在大多数情况下,你的应用程序处于不稳定的状态,你不应该继续。 但是,要真正回答这些情况:“是的,你可以恢复和继续当你赶上,但你应该只尝试恢复,并继续抛出的API指出,支持恢复如果问题是无法控制的,这个问题并不是例外的(例如找不到文件),而供应商真的希望你继续下去,那么我将不得不假设你继续下去,尽pipe它确实不是(100%安全的)。“ 不要尝试从顶层exception处理程序中恢复/继续(程序在返回后将中止)。 如果你想变得非常花哨,立即在OSX上展示,另一个过程将是最好的。 如果你是通过一个纯粹的C ++接口来调用,那么展开的定义是很好的,而且需要捕获是必要的 – 如果可以恢复,就要继续。 C ++中的exception可以被恢复和定义好 – 它们也被广泛地使用(包括less于特殊的条件)。

(IMO …)不应该引入ObjC中的exception,并且应该弃用从系统或第三方库中引发的任何方法。 他们不能放松,或者以一个明确的方式。 同样的,展开stream程正常的cocoa程序stream程。 这意味着触摸抛出时在突变中的所有objc对象的内存/关系,以及位于throw和catch之间的objc对象的内存/关系就像未定义的行为一样好。 问题是 – 你不知道记忆是什么(在大多数情况下,在合理的维护时间内)。 C ++exception是很好定义的,它们可以正确解开(比如调用析构函数),但是试图在ObjC上下文中忽略未定义行为的后果。 国际海事组织,他们应该只存在ObjC ++(因为C ++要求他们)。

在一个理想的世界里,你的ObjC程序和你使用的库不会使用exception(根本)。 既然你使用了抛出的库(包括Cocoa), 那么只有当你需要关于错误的特殊信息的时候才安装一个顶级的exception处理器。 如果API要求您可以预料到由于无法控制的情况而抛出的exception,并希望恢复 ,那么请编写一个catch语句,但立即将该逻辑转换为正常的程序stream(例如NSError ) – 您永远不需要编写自己的抛出。 -[NSArray objectAtIndex:和“对象不响应select器”是程序员错误的例子 – 他们不应该被捕获,但程序应该纠正。