ans*_*hul 3 iphone exception-handling objective-c nsexception ios
我对iPhone中的异常处理有一些疑问.他们是:
假设我有一个被一个接一个地调用的方法链,也就是说,方法A调用方法B,方法B又调用方法C,它调用方法D.这是放置try-catch块的最佳位置(是方法A或B,C或D或所有方法).此外,我需要向用户显示发生异常的警报,然后,我想将此异常记录到我的服务器.所以,如果我在所有这些方法中编写try-catch块,并且在方法D中发生异常; 然后我认为警报将显示4次,并且用于记录的Web服务也将被调用4次(直到控制到达方法A的捕获块).那么,我应该只使用@throw; 在方法B,C和D的catch块中,将我的逻辑写入方法A的catch块(顶层方法),或者我应该避免在方法B,C和D中编写try-catch.
我需要来自异常的某种错误代码(因为我的Web服务需要参数错误代码和描述).是否可以将异常转换为错误,还是需要对此代码进行硬编码?
我读过有关NSSetUncaughtExceptionHandler的内容.而且我认为,如果我可以设置这个处理程序(在appDate的appDidFinishLaunching方法中)和处理程序方法,如果我向用户显示一些警报并调用web服务; 那么我不需要在每个类中的每个方法中编写try-catch块.我对吗??
如果发生异常并且我编写了try-catch块或NSSetUncaughtExceptionHandler,那么我的应用程序将继续运行,或者它不会响应任何用户事件.(我相信它会处理崩溃.我想知道的是它是否会挂起)
有人请在这个EXCEPTION主题上赐教.
jus*_*tin 19
0)避免Cocoa中的异常.它们通常是不可恢复的.您可能会因为自己的错误报告而捕获它们,但假设您可以从它们中恢复通常是不安全的.
1)如果你需要抓住,立即抓住它.不要写自己的投掷 - 而是将其转换为类似的东西NSError并传递它.NSError可以包含显示或发送错误代码以及本地化消息所需的所有信息.
2)你不能将a NSException转换为NSError(直接)因为NSException没有所有属性NSError- 它是一个不同的数据表示.例如,错误代码不可用.二,描述不是本地化的.您可以做的最好的事情是创建一个错误代码和域,然后使用您需要的属性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);
...
}
Run Code Online (Sandbox Code Playgroud)
如果您使用的API抛出异常,您应该捕获并从中恢复(例如,不是真正的例外情况),那么是的,您可以捕获并尝试继续.不幸的是,任何在Cocoa中编写异常并且意图捕获它们的人可能都不能很好地理解这些问题以实现一个可靠的展开实现(例如,即使它产生泄漏,它也不稳定).
3)真的不是显示警报的时间或地点.如果您安装顶级异常处理程序(via NSSetUncaughtExceptionHandler) - 您应该只记录一条消息 - 然后异常处理程序将中止.您的应用处于不稳定状态 - 持续比中止更糟糕.您可能希望将这些自定义消息发送回家,最好在下次启动应用时执行此操作.
4)在大多数情况下,您的应用程序处于不稳定状态,您不应该继续.但是,要真正回答这些极端情况:"是的,你可以恢复并在你捕获时继续,但你应该只尝试恢复并继续当抛出API指出恢复得到支持.如果问题超出你的控制,并且问题不是例外(例如找不到文件),供应商真的希望你继续,然后我必须假设他们希望你继续,即使它确实不是(100%安全)." 不要尝试从顶级异常处理程序中恢复/继续(程序将在返回后中止).如果您想要非常喜欢并立即在OSX上呈现,那么另一个过程将是最好的.如果您通过纯C++接口进行调用,则可以很好地定义展开,并且需要捕获 - 如果可以恢复则继续.C++中的异常可以恢复和定义良好 - 它们也被广泛使用(包括不太特殊的条件).
(IMO ...)不应该引入ObjC中的异常,并且不应该弃用从系统或第三方库引发的任何方法.它们不能很好地展开,也不能以明确的方式展开.同样,解除正常Cocoa程序流程的流量.这意味着触摸任何objc对象的内存/关系,这些内存/关系在抛出时处于变异状态,位于throw和catch之间,与未定义的行为一样好.问题是 - 你不知道那个记忆是什么(在大多数情况下,并且在合理的维护时间内).C++异常定义得很好,并且它们正确展开(例如调用析构函数) - 但是尝试在ObjC上下文中继续忽略未定义行为的任何后果.IMO,它们只应存在于ObjC++中(因为C++需要它们).
在理想的世界中,您的ObjC程序和您使用的库不会使用异常(根本).由于您使用了抛出的库(包括Cocoa),因此只有在需要有关错误的特殊信息时才安装顶级异常处理程序.如果API强制要求您因为无法控制的情况而抛出异常,并且您需要恢复,那么请编写一个catch但立即将该逻辑转换为正常的程序流(例如NSError) - 您永远不需要编写自己的抛出.-[NSArray objectAtIndex:和"对象不以选择回答"是程序员的错误例子-他们应该不会被抓到,但该方案应予以纠正.
| 归档时间: |
|
| 查看次数: |
3255 次 |
| 最近记录: |