1

我有一个方法,它有几个部分可以引发异常。如果这些部件之一发生故障,我希望运行清洁方法。我正在考虑使用 try/catch 指令。

我的问题是:我是否必须对可能引发异常的每一行代码使用一个指令,或者我可以简单地将整个方法包含在这样的块中?

 @try {
    [self doStuff];
     // doStuff has several passages that could throw an exception

 }
 @catch (NSException * e) {
    [self cleanTheWholeThing];
 }

在这种情况下,哪条线路产生问题对我来说并不重要。我只需要该方法成功运行或做其他事情以防它失败。

谢谢

4

6 回答 6

5

如果可以,请避免异常。甚至 Apple 也建议避免使用它们

代替异常,错误对象(NSError)和 Cocoa 错误传递机制是在 Cocoa 应用程序中传达预期错误的推荐方式。

另请参阅他们的错误处理编程指南(它被标记为与 Mac 相关,但对 iPhone 同样有效,同样的概念适用)。

我知道避免异常的原因是:

  • 它们比通过 NSError 和外指针报告要慢。
  • 如果您不小心,它们可能会导致内存泄漏。由于异常导致的一些内存泄漏根本无法避免(在非 GC 环境中)。
  • 您可能会忘记捕捉它们,然后您的应用程序就会崩溃。

一般来说,Objective-C 中的异常用于处理通常无法恢复的异常问题。它们几乎从不用于您预计可能会出错的区域(例如网络通信;这些NSURLConnection方法不会因此引发异常,而是导出一个NSError)。这可能与其他更经常使用异常的语言不同。在我一直从事的项目中,我只有一次需要捕获和处理异常(但不记得是哪个)。

相反,您应该这样做:

// Returns YES when successful.
- (BOOL)doSomething:(NSError **)outError
{
    // ...
    if (someErrorOccurred) {
        if (outError) {
           outError = [NSError
               errorWithDomain:@"MyErrorDomain"
               code:123
               userInfo:nil
           ];
           // Or maybe even use your own NSError subclass
           return NO;
        }
    }

    // ...
    // Operation was successful.
    return YES;
}
于 2011-06-25T11:44:31.523 回答
4

你的 try 块中当然可以有多行。例子:

@try {
    if (managedObjectContext == nil) {
        actionMessage = @"accessing user recipe library";
        [self initCoreDataStack];
    }
    actionMessage = @"finding recipes";
    recipes = [self recipesMatchingSearchParameters];
    actionMessage = @"generating recipe summaries";
    summaries = [self summariesFromRecipes:recipes];
}
@catch (NSException *exception) {
    NSMutableDictionary *errorDict = [NSMutableDictionary dictionary];
    [errorDict setObject:[NSString stringWithFormat:@"Error %@: %@", actionMessage, [exception reason]] forKey:OSAScriptErrorMessage];
    [errorDict setObject:[NSNumber numberWithInt:errOSAGeneralError] forKey:OSAScriptErrorNumber];
    *errorInfo = errorDict;
    return input;
} @catch (OtherException * e) {
    ....
} @finally {
    // Any clean up can happen here.  
    // Finally will be called if an exception is thrown or not.
}

以及异常实际使用的链接:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Exceptions/Tasks/HandlingExceptions.html

于 2011-06-25T11:32:57.427 回答
2

用 try-catch 块封装方法调用是完全可以的。

于 2011-06-25T11:31:33.310 回答
1

如果您不关心哪一行导致了异常,您可以将整个函数包含在 try/catch 块中。

例如,假设 f1()、f2() 或 f3() 可以在此代码中引发异常:

try {
   f1();
   f2();
   f3();
}
catch( ... ) {

 ...either f1, f2 or f3 threw an exception - don't know which
}
于 2011-06-25T11:29:06.487 回答
0

您可以在try块中包含整个方法主体。

就您而言catch,您可以有多个catch块来处理不同类型的异常:

 @catch (NSException * e) {
   ....
 }
 @catch (OtherException * e) {
    ....
 }
 @finally {
    NSLog(@"finally");
 }

因此,如果您需要,您还可以根据引发的特定异常准确识别哪条线失败。

于 2011-06-25T11:26:46.813 回答
0

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Exceptions/Tasks/HandlingExceptions.html 您可以在 try 块中包含整个方法体。

于 2014-03-26T07:03:52.373 回答