iphone - 尝试,抓住问题

时间:2011-06-25 11:24:22

标签: iphone objective-c ios nsexception

我有一个方法有几个部分可以抛出异常。如果其中一个部件出现故障,我希望清洁方法能够运行。我正在考虑使用try / catch指令。

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

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

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

在这种情况下,对我来说哪一行产生问题并不重要。我只需要成功运行该方法或在其失败时执行其他操作。

感谢

6 个答案:

答案 0 :(得分:5)

如果可以,请避免例外。 Even Apple recommends to avoid them

  

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

另请参阅他们的Error Handling Programming Guide(标记为与Mac相关,但同样适用于iPhone,适用相同的概念)。

避免例外的原因是我所知道的是:

  • 它们比通过NSError和out-pointer报告要慢。
  • 如果您非常小心,它们可能会导致内存泄漏。由于异常导致的一些内存泄漏根本无法避免(在非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;
}

答案 1 :(得分: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

答案 2 :(得分:2)

  

用try-catch块封闭方法调用完全没问题。

答案 3 :(得分:1)

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

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

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

 ...either f1, f2 or f3 threw an exception - don't know which
}

答案 4 :(得分:0)

您可以在try区块中包含整个方法正文。

catch部分中,您可以拥有多个catch块来处理不同类型的例外:

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

因此,如果您需要,您还可以根据引发的特定异常确切地辨别出哪一行失败。

答案 5 :(得分:0)