あなたの理解は正しいです-NSError(または同様のもの)は、例外ではなく、エラー情報を伝えるために使用されるべきです。ほとんどのObjective-Cコードは例外に対して安全ではなく、少なくともリソースをリークします。原則として、Appleであろうとサードパーティであろうと、コードが他の誰かのコードに例外を漏らさないようにしてください。一部のサードパーティフレームワークは、例外的に安全であることを明示的に示している場合がありますが、それはまれです。
その原則により、メソッドにキャッチオール例外ハンドラーが必要な理由がわかりますmain
。ただし、実際には別の理由があります。操作は専用スレッドで実行されます。操作からスローされた例外はスタックに伝播しますが、それ以上は伝播しません。論理的な呼び出し元または操作の所有者は、別のスレッドで実行されている(またはまったく実行されていない)ため、それらを取得しません。したがって、リークされた例外は、プログラム全体を強制終了するか、他の兆候なしに黙って飲み込まれます。その後、プログラムが奇妙な状態でスタックする可能性があります。エラーが発生したことに気づかなかったため、操作の結果が届かないのを待ち続けることができます。
さらに、Appleには、同時実行プログラミングガイドに、エラーと例外の処理について説明しているセクションがあります。「個別の実体」に関する彼らの最初のポイントは、前の段落で私が言ったことをほのめかしています。
エラーと例外の処理
操作は基本的にアプリケーション内の個別のエンティティであるため、発生するエラーや例外を処理する責任があります。OS X v10.6以降では、NSOperationクラスによって提供されるデフォルトのstartメソッドは例外をキャッチしません。(OS X v10.5では、startメソッドは例外をキャッチして抑制します。)独自のコードは常に例外を直接キャッチして抑制します。また、エラーコードを確認し、必要に応じてアプリケーションの適切な部分に通知する必要があります。また、startメソッドを置き換える場合は、カスタム実装で例外をキャッチして、基になるスレッドのスコープを離れないようにする必要があります。
処理する準備が必要なエラー状況のタイプには、次のものがあります。
- UNIXのerrnoスタイルのエラーコードを確認して処理します。
- メソッドと関数によって返される明示的なエラーコードを確認します。
- 独自のコードまたは他のシステムフレームワークによってスローされた例外をキャッチします。
- NSOperationクラス自体によってスローされた例外をキャッチします。これにより、次の状況で例外がスローされます。
- 操作を実行する準備ができていないが、そのstartメソッドが呼び出された場合
- 操作が実行中または終了したとき(おそらくキャンセルされたため)、そのstartメソッドが再度呼び出されたとき
- すでに実行中または終了している操作に完了ブロックを追加しようとした場合
- キャンセルされたNSInvocationOperationオブジェクトの結果を取得しようとしたとき
カスタムコードで例外またはエラーが発生した場合は、そのエラーをアプリケーションの残りの部分に伝播するために必要な手順を実行する必要があります。NSOperationクラスは、エラー結果コードまたは例外をアプリケーションの他の部分に渡すための明示的なメソッドを提供しません。したがって、そのような情報がアプリケーションにとって重要である場合は、必要なコードを提供する必要があります。