我是Objective-C的新手,我发现有关于错误处理的不同约定。有一些例外,但也有一些情况,如果出现问题,函数应该返回nil。
那么,我如何决定何时使用哪个,以及如何处理异常和意外的返回值?什么是最佳做法和危险信号?
答案 0 :(得分:35)
我不会确定使用哪个,但这里有关于每个选项的一些信息:
Obj-C中的异常并不真正用于控制程序流程。来自documentation on exception handling:
一般模式是异常仅为程序员错误保留,并且捕获此类异常的程序应该很快就会退出。
出于这个原因,我不建议仅使用例外@try
/ @catch
来测试方法是否正常工作。
除了设置更高级several options for handling exceptions之外,您还有uncaught exception handler。
错误通常以三种方式使用:
对象可以在指定的错误处理回调函数中将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...];
。)由于此模式的线性特性,它最适合用于同步任务。
自引入块以来的一个相当新的模式,但是非常有用的模式:
- (void)performAsynchronousTaskWithCompletionHandler:(void (^)(BOOL success, NSError *error))handler;
像这样使用:
[myObject performAsynchronousTaskWithCompletionHandler:^(BOOL success, NSError *error) {
if (!success) {
// ...
}
}];
这变化很大:有时你不会看到布尔参数,只看错误;有时处理程序块没有传递给它的参数,你只需检查对象的状态属性(例如,这就是AVAssetExportSession的工作原理)。当您需要基于块的方法时,此模式对于异步任务也很有用。
Mac OS X上的Cocoa有一个quite thorough error-handling path。还有NSAlert的便捷方法+ (NSAlert *)alertWithError:(NSError *)error;
。在iOS上,NSError类仍然存在,但是没有相同的便捷方法来处理错误。你可能不得不自己做很多事情。
阅读Error Handling Programming Guide了解更多信息。
这通常与NSError out参数一起使用;例如,NSData的方法
+ (id)dataWithContentsOfFile:(NSString *)path
options:(NSDataReadingOptions)mask
error:(NSError **)errorPtr;
如果读取文件失败,此方法将返回nil
,并且更多信息将存储在错误中。
这是一个特别方便的模式的一个原因是因为nil messaging,这可以安全地完成而在Obj-C中没有效果。我不会在这里详细说明为什么这是有用的,但你可以在其他地方的互联网上阅读更多关于它的内容。 (只要确保找到一篇最新的文章;它曾经是返回浮点值的方法在发送到nil时不一定会返回0,但现在它们会这样做,如文档中所述。)
答案 1 :(得分:6)
在Objective-C中应尽可能少地使用异常。在其他语言使用异常的情况下,在Objective-C中,建议大多数时候使用NSError对象。
Apple关于异常处理的文档在这里:http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/Exceptions/Exceptions.html%23//apple_ref/doc/uid/10000012il
那么如何使用NSError对象呢?好吧,如果我们查看Apple的类,使用间接指针返回错误。
例如:
- (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 (error)
{
// handle error, perhaps show an alert view ...
}
else
{
// use the object, all went fine ...
}
}
答案 2 :(得分:0)
如果一个方法应该返回一个对象,并且它不能这样做,它应该返回nil。如果您要向用户报告错误,以便他们可以对其采取某种操作,请使用NSError对象。
答案 3 :(得分:0)
Objective-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
}
详细了解错误处理apple doc。