您的位置:首页 > 移动开发 > Objective-C

Objective-C 苹果开发文档 09 Dealing with Errors

2015-08-25 18:52 489 查看


DealingwithErrors

几乎所有的程序都会遇到错误。一些错误可能超出了你的控制范围,比如耗尽了内存空间或者失去了网络连接。一些错误是可以避免的,比如用户的无效输入。即使所有的开发人员都是精益求精的,程序设计员偶尔也会发生错误。

如果你之前从事的是其他的平台和语言,你可能习惯使用异常来处理大多数的错误。当你用OC编写代码时,异常仅仅用于程序员错误,比如数组边界溢出的问题或者无效的方法参数。这些问题都是在你的程序上架之前可以发现并且改正的。

其他的错误都是用NSError类表示的。本章主要介绍如何使用NSError对象,包括如何处理框架方法失败和返回错误的问题。详见Error
HandlingProgrammingGuide。


UseNSErrorforMostErrors

在任何应用的生命周期内,错误都是不可避免的。例如,如果你需要从一个远程的web服务请求一个数据,会有各种各样的潜在问题出现,例如:

Nonetworkconnectivity无网络连接

Theremotewebservicemaybeinaccessible远程网络服务不可到达

Theremotewebservicemaynotbeabletoservetheinformationyourequest远程web服务器没有你需要的信息

Thedatayoureceivemaynotmatchwhatyouwereexpecting你收到的数据和你需要的不匹配

遗憾的是,你不可能制定一个应急的计划,从而解决每一个可能发生的错误。相反,你只能为错误定制出一个计划,并且知道如何处理她们,从而给出最好的用户体验。


SomeDelegateMethodsAlertYoutoErrors

如果你使用一个框架类实现一个委托对象,从而执行一个特定的任务,比如从远程的web服务器下载信息,你会使用一个典型的错误处理方法。NSURLConnectionDelegate协议,包括一个connection:didFailWithError:方法:

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

如果有一个错误出现,这个代理方法会被调用,从而提供给你一个NSError对象来描述错误的问题。
一个NSError对象包括一个数字错误代码,域名和描述,以及其他的相关信息,都被打包在一个用户信息字典里。
不是为每个可能的错误都分配一个特殊的数字代码,Cocoa和CocoaTouch中的错误被划分为许多区域。如果一个错误放生在NSURLConnection,上面的connection:didFailWithError:方法就会从NSURLErrorDomain提供一个错误。
错误对象也包含一个局部的描述,比如“Aserverwiththespecifiedhostnamecouldnotbefound.”(指定的主机名未被找到。)


SomeMethodsPassErrorsbyReference

一些Cocoa和CocoaTouch接口会通过引用来传回错误。例如,你可能需要把一个来自远程web服务器的数据写入到磁盘中,使用NSData方法writeToURL:options:error。方法中的最后一个参数就是一个NSError的指针。

-(BOOL)writeToURL:(NSURL*)aURL

options:(NSDataWritingOptions)mask

error:(NSError**)errorPtr;

Beforeyoucallthismethod,you’llneedtocreateasuitablepointersothatyoucanpassitsaddress:

NSError*anyError;

BOOLsuccess=[receivedDatawriteToURL:someLocalFileURL

options:0

error:&anyError];

if(!success){

NSLog(@"Writefailedwitherror:%@",anyError);

//presenterrortouser

}

如果发生一个错误,writeToURL:...方法会返回一个NO,刷新一个你的anyError指针指向一个错误对象来描述这个问题。
当通过引用来处理错误传递时,你需要测试一下方法的返回值,看看返回值是否会引发一个错误,就像上面显示的那样。不要只是测试错误指针是否被设置为指向一个错误。

Tip:如果你对错误对象不感兴趣,只需要给error:参数传递一个NULL。


RecoverifPossibleorDisplaytheErrortotheUser

最好的用户体验是将你的应用在一个错误中透明的恢复过来。例如,你发送了一个远程web服务器请求,如果未成功的话你可以试着再请求一次不同的服务器。这一次你可能需要对用户请求额外的数据,比如有效的用户名或者密码证书在尝试之前。
如果不能从一个错误中恢复程序,你应该警告用户。如果你为iOS使用CocoaTouch,你需要创建安装一个UIAlertView用来显示错误。如果你为OSX使用Cocoa,你需要调用presentError:为任何NSResponder对象(比如一个视图,窗口或者程序对象自己本身),错误会向上传递相应器链条,为了更深层次的配置或者恢复。当她到达应用对象的时候,应用会通过一个警示面板显示错误给用户。
Formoreinformationonpresentingerrorstotheuser,seeDisplaying
InformationFromErrorObjects.


GeneratingYourOwnErrors

Inordertocreateyourown
NSError
objectsyou’llneedtodefineyourownerrordomain,whichshouldbeoftheform:
为了创建你自己的NSError对象,你需要定义你自己的错误域,形式如下:

com.companyName.appOrFrameworkName.ErrorDomain

You’llalsoneedtopickauniqueerrorcodeforeacherrorthatmayoccurinyourdomain,alongwithasuitabledescription,whichisstoredintheuserinfodictionaryfortheerror,likethis:
你需要为每个在你的错误域中可能发生的每个错误挑选一个特别的错误代码,同时需要一个合适的描述,描述存储在用户信息字典里,像这样:

NSString*domain=@"com.MyCompany.MyApplication.ErrorDomain";

NSString*desc=NSLocalizedString(@"Unableto…",@"");

NSDictionary*userInfo=@{NSLocalizedDescriptionKey:desc};


NSError*error=[NSErrorerrorWithDomain:domain

code:-101

userInfo:userInfo];

Thisexampleusesthe
NSLocalizedString
functiontolookupalocalizedversionoftheerrordescriptionfroma
Localizable.strings
file,
asdescribedinLocalizingStringResources.
Ifyouneedtopassbackanerrorbyreferenceasdescribedearlier,yourmethodsignatureshouldincludeaparameterforapointertoapointertoan
NSError
object.
Youshouldalsousethereturnvaluetoindicatesuccessorfailure,likethis:

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

Ifanerroroccurs,youshouldstartbycheckingwhetheranon-
NULL
pointerwasprovidedfortheerrorparameterbeforeyou
attempttodereferenceittosettheerror,beforereturning
NO
to
indicatefailure,likethis:

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

...

//erroroccurred

if(errorPtr){

*errorPtr=[NSErrorerrorWithDomain:...

code:...

userInfo:...];

}

returnNO;

}


ExceptionsAreUsedforProgrammerErrors

OC和其他的程序语言一样也支持异常用法,类似Java或者C++的语法。和NSError一样,异常在Cocoa和CocoaTouch中都是对象,通过NSException类实例表示。
如果你需要写一个抛出异常的代码,你可以把代码封装到try-catch块中:
@try{

//dosomethingthatmightthrowanexception

}

@catch(NSException*exception){

//dealwiththeexception

}

@finally{

//optionalblockofclean-upcode

//executedwhetherornotanexceptionoccurred

}

如果@try块中的代码抛出了一个异常,就会被@catch块捕获以便于你可以处理异常。如果你处理一个底层级的C++库并且使用异常作为错误处理方法,例如,你可以捕获她的异常,然后生成合适的NSError对象,显示给用户。
如果抛出一个异常没被捕获,那么默认的未捕获异常操作会输出一条消息在控制台上,同时终止程序运行。
你不应该使用try-catch块代替标准的OC方法检测。在NSArray的例子中,你应该总是检查一个数组中元素的个数,以便在使用下标访问之前确定好数组的下标。如果你的使用越界,objectAtIndex:方法会抛出异常,这样你就可以提前发现错误——在你将应用展示给用户的时候,你应该避免抛出异常。
FormoreinformationonexceptionsinObjective-Capplications,seeException
ProgrammingTopics.

NextPrevious
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: