当前位置 : 主页 > 网络编程 > 其它编程 >

9.错误处理DealingwithErrors

来源:互联网 收集:自由互联 发布时间:2023-07-02
错误处理几乎每一款应用都会遇到错误。其中一些错误会超出你的控制,比如用光了磁盘空间或丢失了网络连接。其中一些错误是可以恢复的,如无效的用户输入。并且,虽然所有的开
错误处理几乎每一款应用都会遇到错误。其中一些错误会超出你的控制,比如用光了磁盘空间或丢失了网络连接。其中一些错误是可以恢复的,如无效的用户输入。并且,虽然所有的开发人员都在努力追求 错误处理

几乎每一款应用都会遇到错误。其中一些错误会超出你的控制,比如用光了磁盘空间或丢失了网络连接。其中一些错误是可以恢复的,如无效的用户输入。并且,虽然所有的开发人员都在努力追求完美,但程序员偶尔也会出现错误。

如果你是来自其他平台和语言的开发者,你过去常常可能使用异常(exceptions)来处理大多数的错误。当你使用 Objective-C 编写代码时,异常(exceptions)仅针对于程序员的错误,如数组的访问越界或无效的方法参数。这些问题是在你应用程序启动之前,在进行测试的时候就应该找到并修复的。

所有其他错误都是NSError类实例化的表现。本章给出了使用NSError对象的简要介绍,包括如何使用框架的方法可能会失败并返回错误。需要更多信息,请参见Error Handling Programming Guide

使用NSError处理大多数错误

错误是许多应用程序生命周期中不可避免的一部分。如果你需要从远程Web服务器请求数据,可能会出现各种各样的问题,比如:

  • 没有网络连接
  • 远程服务器可能无法访问
  • 远程服务器可能无法返回你请求的信息
  • 你收到的数据可能不符合你的期望

遗憾的是,不可能为每一个可能遇见的问题做应急预案和解决方案。取而代之的是,你必须为错误作出计划并且知道怎样处理它们,并带来最好的用户体验。

一些代理方法会提示你错误

如果你正在实现一个框架类(framework class)的代理对象(delegate object)用于执行某个特定的任务,如从远程Web服务器中下载信息,则通常会发现你至少需要实现一个与错误相关的方法。例如,NSURLConnectionDelegate协议,包括一个connection:didFailWithError:方法:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

如果出现一个错误,这个代理方法会被调用并给你提供一个NSError对象来描述问题。

一个NSError对象包含一个数字错误代码(numeric error code),域(domain)和描述(description),以及被封装在一个用户信息字典(user info dictionary)中的其他相关信息。

相较于要求每一个可能的错误都有一个独特的数字代码,Cocoa和Cocoa Touch的错误被分为域(domins)。比如,如果发生一个NSURLConnection的错误,这个connection:didFailWithError:方法将提供来自NSURLErrorDomain的一个错误。

这个错误对象还包含一个本地化描述(localized description),如“找不到指定的服务器”。

一些方法通过参数传递错误

一些Cocoa和Cocoa Touch的接口(API)通过参数传回错误。例如,你可能决定使用NSData的方法writeToURL:options:error:,将你从Web服务器接收到的数据通过写入磁盘保存起来。这个方法的最后一个参数是对NSError指针的引用:

- (BOOL)writeToURL:(NSURL *)aURL options:(NSDataWritingOptions)mask error:(NSError **)errorPtr;

在你调用此方法之前,你需要创建一个合适的指针,以便你可以传入它的地址:

NSError *anyError; BOOL success = [receivedData writeToURL:someLocalFileURL options:0 error: if (!success) { NSLog(@"Write failed with error: %@", anyError); // present error to user }

如果出现了错误,这个writeToURL:...方法将会返回NO,并更新你的anyError指针指向错误的对象来描述问题。

当处理参数传递的错误时,通过测试方法的返回值来查看是否发生了错误非常重要,如上面所示。不要仅仅只是测试查看这个错误指针是否被设置为指向了一个错误。

提示:如果你对错误对象不敢兴趣,只需要给error:参数传NULL就行了。

如果可能的话尽量恢复或向用户显示错误

最好的用户体验就是让你的应用程序显而易见地从错误中恢复。如果你正在制作一个远程Web请求,比如,你可能会尝试使用不同的服务器重新发送请求。或者你可能需要在再次请求之前从用户获取更多信息,比如有效的用户名或密码凭据。

如果它不可能从错误中恢复,你应该提醒用户。如果你正在使用Cocoa Touch为iOS开发,你需要创建和配置一个UIAlertView来显示错误。如果你在使用Cocoa为OS X(mac OS)开发,你可以在任何NSResponder对象(如视图、窗口或应用程序对象本身)调用presentError:并且错误会随响应链(responder chain)传递以寻求更多配置或恢复。当它到达应用程序对象时,应用程序通过一个警告面板向用户呈现错误。

更多有关向用户展现错误的信息,请参见 Displaying Information From Error Objects。

创建你自己的错误对象

为了创建自己的NSError对象,你需要定义你自己的错误域(domain),它应该是这样的形式:

com.companyName.appOrFrameworkName.ErrorDomain

你还需要为每一个可能发生在你域(domain)中的错误选择一个唯一的错误代码,以及一个合适的描述,它被存储在用户信息字典(user info dictionary)中,像这样:

NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";NSString *desc = NSLocalizedString(@"Unable to…", @"");NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };NSError *error = [NSError errorWithDomain:domain code:-101 userInfo:userInfo];

这个示例使用NSLocalizedString函数从一个Localizable.strings文件来查找错误描述的本地化版本,作为本地化字符串资源(Localizing String Resources)的描述。

如果你需要通过参数传回一个错误作为早期描述,你的方法签名(method signature)应该包含一个指向NSError对象的指针作为参数。你也应该使用返回值来表示成功或者失败,如:

- (BOOL)doSomethingThatMayGenerateAnError:(NSError **)errorPtr;

如果出现错误,在你尝试引用它来设置错误之前,你首先应该检查是否给错误指针提供了一个非空指针,在返回NO来表示失败之前,像这样:

- (BOOL)doSomethingThatMayGenerateAnError:(NSError **)errorPtr { ... // error occurred if (errorPtr) { *errorPtr = [NSError errorWithDomain:... code:... userInfo:...]; } return NO;}

异常用来处理程序员的错误

Objective-C支持异常(exceptions),有和其他许多编程语言有相同的用法,和Java或C++有相似的语法。和NSError一样,在Cocoa和Cocoa Touch中的异常都是对象,通过NSException类的实例来表示。

如果你需要编写可能引发异常的代码,你可以将该代码封装在一个try-catch代码块(block)中:

@try { // do something that might throw an exception}@catch (NSException *exception) { // deal with the exception}@finally { // optional block of clean-up code // executed whether or not an exception occurred}

如果一个异常被在@try代码块中的代码抛出,它将会被@catch代码块捕获,你便可以处理它。比如,如果你在使用用异常(exceptions)来处理错误的底层C++库,你可能会捕获到异常并创建合适的NSError对象来向用户显示。

如果一个异常被抛出但没有被捕获,默认的没有捕获异常处理会记录信息到控制台并终止程序。

你不应该在标准程序检查Objective-C方法的地方使用try-catch代码块。以一个NSArray为例,你应该在试图访问指定下标的对象之前,总是检查数组的count来确定元素的数量。如果你做了一个越界的访问请求,objectAtIndex:方法会抛出一个异常,在开发周期的早期你就可以找到在你代码中的漏洞(bug),你在给用户的应用中应该避免抛出异常。

想了解更多关于在Objective-C程序中异常的信息,请参考Exception Programming Topics。

【感谢龙石为本站提供数据质量管理系统,http://www.longshidata.com/pages/quality.html】
网友评论