处理错误 Dealing with Errors

几乎每个应用程序都会遇到错误。其中一些错误将超出您的控制范围,例如耗尽磁盘空间或丢失网络连接。其中一些错误将是可恢复的,例如无效的用户输入。而且,尽管所有开发人员都力求完美,但偶尔也会出现程序员错误。

如果您来自其他平台和语言,那么您可能习惯于处理大多数错误处理的异常。当您使用Objective-C编写代码时,异常仅用于程序员的错误,如边界数组访问或无效的方法参数。这些问题是您在发布应用程序之前应该发现并修复的问题。

所有其他错误都由NSError类的实例表示。本章简要介绍了使用NSError对象,包括如何使用可能失败和返回错误的框架方法。有关进一步的信息,请参见错误处理编程指南 Error Handling Programming Guide

对大多数错误使用NSError

错误是任何应用程序生命周期中不可避免的一部分。例如,如果您需要从远程web服务请求数据,可能会出现各种各样的潜在问题,包括:

  • 没有网络连接

  • 远程web服务可能无法访问

  • 远程web服务可能无法提供您请求的信息

  • 你收到的数据可能与你预期的不符

遗憾的是,我们不可能为每个可能出现的问题建立应急计划和解决方案。相反,您必须计划错误并知道如何处理它们以提供最佳的用户体验。

一些委托方法会提醒您错误

如果您正在实现一个用于执行特定任务的框架类的委托对象,比如从远程web服务下载信息,您通常会发现您需要实现至少一个错误相关的方法。例如,NSURLConnectionDelegate协议包含一个connection:didFailWithError:方法:

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

如果出现错误,将调用此委托方法为您提供一个NSError对象来描述问题。

NSError对象包含一个数字错误代码、域和描述,以及在用户信息字典中打包的其他相关信息。

而不是要求每个可能的错误都有唯一的数字代码,Cocoa和Cocoa Touchu错误被划分为域。如果在NSURLConnection中发生错误,例如,connection:didFailWithError:上面的方法将提供来自NSURLErrorDomain的错误。

错误对象还包括一个本地化描述,例如“无法找到具有指定主机名的服务器(A server with the specified hostname could not be found.)”。

有些方法通过引用来传递错误

一些Cocoa和Cocoa Touch API通过引用来传递错误。例如,您可能决定将从web服务接收到的数据写入磁盘,使用NSData方法writeToURL:options:error:。该方法的最后一个参数是对NSError指针的引用:

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

在调用此方法之前,您需要创建一个合适的指针,以便通过它的地址:

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

如果出现错误,writeToURL:…方法将返回NO,并更新您的anyError指针以指向描述该问题的错误对象。

当处理通过引用传递的错误时,重要的是测试方法的返回值,以查看是否发生了错误,如上所示。不要只是测试看错误指针是否被设置为指向错误。

提示:如果您对错误对象不感兴趣,请为错误参数传递NULL.

如果可能,请恢复,或向用户显示错误

最好的用户体验是让你的应用程序从错误中透明地恢复。例如,如果您正在创建一个远程web请求,您可以尝试使用不同的服务器再次发出请求。或者,您可能需要在再次尝试之前向用户请求其他信息,比如有效的用户名或密码凭证。

如果无法从错误中恢复,应该提醒用户。如果您正在为iOS开发Cocoa Touch,那么您需要创建和配置一个UIAlertView来显示错误。如果您正在为OS X开发Cocoa,您可以调用presentError:在任何NSResponder对象(比如视图、窗口,甚至是应用程序对象本身)上,错误将会传播到responder chain以进行进一步的配置或恢复。当它到达应用程序对象时,应用程序通过一个警告面板向用户呈现错误。

有关向用户显示错误的更多信息,请参见从错误对象中显示信息Displaying Information From Error Objects。

创造你自己的错误

为了创建自己的NSError对象,您需要定义自己的错误域,该域应该是:

com.companyName.appOrFrameworkName.ErrorDomain

您还需要为域中可能发生的每个错误选择一个惟一的错误代码,以及一个适当的描述,该描述存储在用户信息字典中,用于错误,如下所示:

    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函数从可本地化的地方查找错误描述的本地化版本。字符串文件,如本地化字符串资源所述。

如果您需要像前面描述的那样通过引用传递一个错误,那么您的方法签名应该包含一个指向指向NSError对象指针的参数。您还应该使用返回值来表示成功或失败,如下所示:

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

如果发生错误,您应该首先检查是否为错误参数提供了一个非空指针,然后尝试取消它来设置错误,然后返回NO表示失败,如下所示:

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

异常用于程序员错误

Objective-C和其他编程语言一样支持异常,类似于Java或c++的语法。与NSError一样,Cocoa和Cocoa Touch中的异常都是对象,由NSException类的实例表示。

如果您需要编写可能导致抛出异常的代码,您可以将该代码封装在try-catch块中:

    @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块捕获,以便您可以处理它。如果您使用的是一个低级c++库,它使用异常处理错误,例如,您可能会捕获它的异常,并生成合适的NSError对象来显示给用户。

如果抛出异常并未捕获异常,则默认的未捕获异常处理程序将消息记录到控制台并终止应用程序。

您不应该使用try-catch块来代替Objective-C方法的标准编程检查。例如,在NSArray的情况下,在尝试访问给定索引的对象之前,应该始终检查数组的计数来确定项目的数量。objectAtIndex:方法会抛出一个异常,如果您做出了一个超出范围的请求,这样您就可以在开发周期的早期发现代码中的错误——您应该避免在您发送给用户的应用程序中抛出异常。

有关Objective-C应用程序中异常的更多信息,请参见异常编程主题 Exception Programming Topics

免责声明:以上内容均来自官方文档 Programming with Objective-C ,在 有道翻译 的基础上进行修改整理,仅用于个人学习。因个人水平有限,如果存在错误,请读者谅解并指出,非常感谢!

你可能感兴趣的:(处理错误 Dealing with Errors)