1

例外をスローできるいくつかの部分を持つメソッドがあります。これらの部品のいずれかが故障した場合は、クリーニング メソッドを実行したいと思います。try/catch ディレクティブの使用を考えています。

私の質問は次のとおりです。例外をスローする可能性のあるコード行ごとに 1 つのディレクティブを使用する必要がありますか?それとも、このようなブロックにメソッド全体を単純に含めることができますか?

 @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 アプリケーションで予想されるエラーを伝達することをお勧めします。

Error Handling Programming Guideも参照してください(Mac 関連としてマークされていますが、iPhone でも同様に有効であり、同じ概念が適用されます)。

私が知っている例外を回避する理由は次のとおりです。

  • それらは、NSError およびアウトポインターを介したレポートよりも遅くなります。
  • 注意しないと、メモリ リークが発生する可能性があります。例外による一部のメモリ リークは、まったく回避できません (非 GC 環境では)。
  • それらをキャッチするのを忘れて、アプリがクラッシュする可能性があります。

一般に、Objective-C の例外は、多くの場合回復不能な非常に例外的な問題に使用されます。これらは、何か問題が発生する可能性があると予想される領域ではほとんど使用されません (ネットワーク通信など。NSURLConnectionメソッドはこの理由で例外をスローせず、 をエクスポートしますNSError)。これは、例外がより頻繁に使用される他の言語とは異なる場合があります。私が取り組んできたプロジェクトでは、例外をキャッチして処理する必要があったのは 1 回だけでした (ただし、どのプロジェクトかは思い出せません)。

代わりに、次のようにする必要があります。

// 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 に答える