我是Objective-C的新手,看到有关错误处理的不同惯例。 有异常,但也有情况下函数只应在出现问题时返回nil。
那么,如何决定使用哪个方法,以及如何处理异常和意外的返回值? 有什么最佳实践和警告标志吗?
我是Objective-C的新手,看到有关错误处理的不同惯例。 有异常,但也有情况下函数只应在出现问题时返回nil。
那么,如何决定使用哪个方法,以及如何处理异常和意外的返回值? 有什么最佳实践和警告标志吗?
我不会确定该使用哪种方式,但以下是关于每个选项的一些信息:
在Obj-C中,异常并不是真正用于控制程序流程的。根据异常处理文档:
通常情况下,仅当发生程序员错误时才会抛出异常,捕获这样的异常的程序应尽快退出。
因此,我不建议仅仅为了测试方法是否正确工作而使用异常@try
/@catch
。
您还可以选择多种处理异常的方式,除此之外还可以设置更高级别的未捕获异常处理程序。
错误通常有三种用法:
一个对象可以在指定的错误处理回调函数中简单地将NSError传递给其委托:
- (void)myObject:(MyObject *)obj didFailWithError:(NSError *)error;
委托可以执行任何适当的操作,包括向用户显示消息。这种模式通常在异步委托API中使用。
这些通常与布尔返回值一起使用:如果返回值为NO
,则可以检查NSError对象以获取有关错误的更多信息。
- (BOOL)performTaskWithParameter:(id)param returningError:(out NSError **)error;
一个可能的使用模式是:
NSError *error;
if (![myObject performTaskWithParameter:@"param" returningError:&error]) {
NSLog(@"Task failed with error: %@", error);
}
有些人更喜欢在检查布尔值之前将结果存储在变量中,例如BOOL success = [myObject perform...];
。由于该模式的线性特性,最适合用于同步任务。
自从引入blocks以来,这是一个相当新的模式,但非常有用:
- (void)performAsynchronousTaskWithCompletionHandler:(void (^)(BOOL success, NSError *error))handler;
使用方式如下:
[myObject performAsynchronousTaskWithCompletionHandler:^(BOOL success, NSError *error) { if (!success) { // ... }}];
这种情况千差万别:有时候你看不到布尔型参数,只能看到错误;有时候处理程序块没有传递参数给它,你只需要检查对象的状态属性(例如,这就是AVAssetExportSession的工作原理)。当你想要一种基于块的方法来处理异步任务时,这种模式也非常适用。
Mac OS X上的Cocoa拥有一个相当完备的错误处理路径。还有NSAlert的方便方法+ (NSAlert *)alertWithError:(NSError *)error;
。在iOS上,虽然存在NSError类,但没有同样方便的方法来处理错误。你可能需要自己处理很多内容。
阅读错误处理编程指南以获取更多信息。
这通常与NSError输出参数一起使用;例如,NSData的方法
+ (id)dataWithContentsOfFile:(NSString *)path
options:(NSDataReadingOptions)mask
error:(NSError **)errorPtr;
如果读取文件失败,这个方法会返回nil
,更多的信息将被保存在错误中。- (NSObject *)objectFromSet:(NSSet *)set error:(NSError **)error
{
// get an object from a set; if the set has at least 1 object
// we return an object, otherwise an error is returned.
NSObject *object = [set anyObject]
if (!object)
{
*error = [NSError errorWithDomain:@"AppDomain" code:1000 userInfo:nil];
return nil;
}
return object;
}
// and then we use the function like this
- (void)test
{
NSError *error = nil;
NSSet *set = [[[NSSet alloc] init] autorelease];
NSObject *object = [self objectFromSet:set error:&error];
if (object)
{
// use the object, all went fine ...
}
else
{
// handle error, perhaps show an alert view ...
}
}
objectFromSet:error:
方法中进行赋值之前,需要检查error
是否为非空(non-NULL)。其次,您不应该通过测试错误来检查错误。必须检查返回值,仅当返回nil时才考虑错误的内容。(此外,在调用者中初始化error
为nil
没有要求。) - bbumNSError
输出参数的实际问题,可以参考这个答案:https://dev59.com/bHI95IYBdhLWcg3w-DH0#2511161(我很惊讶这个问题的被接受的答案是错误的) - ohhorobObjective-C支持异常处理,其语法与Java或C++类似。与NSError
一样,Cocoa和Cocoa Touch中的异常也是对象,由NSException类的实例表示。
您可以使用
@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
}
了解更多关于错误处理的内容苹果文档。