例として次のコードを取り上げます
- (id)init {
self = [super init];
if (self) {
// code
}
return self;
}
nil が呼び出し階層を上に伝播することは望ましくありません。私の最初のアイデアは、self が nil の場合に例外をスローし、復元ポイントを作成して実行を中止することです。
より良いアイデア?
例として次のコードを取り上げます
- (id)init {
self = [super init];
if (self) {
// code
}
return self;
}
nil が呼び出し階層を上に伝播することは望ましくありません。私の最初のアイデアは、self が nil の場合に例外をスローし、復元ポイントを作成して実行を中止することです。
より良いアイデア?
NSObject の実装[super init]
は決して nil を返しません。基本実装は self を返すだけです。
一般に、イニシャライザが nil を返す唯一の理由は、致命的でないエラーが発生した場合です。たとえば-initWithContentsOfURL:error:
、無効な URL を呼び出して渡した可能性があります。慣例により、このように失敗する可能性のあるメソッドにはerror:
、失敗に関する情報を含むパラメーターがあります。ほとんどのイニシャライザは回復可能なエラーの可能性がないため、NSObject と同様に nil を返すことはありません。
致命的なエラーは通常、例外をスローするか、プログラムを中止します。そのため、nil をチェックしても役に立ちません。致命的なエラーを処理するための最善の策はNSSetUncaughtExceptionHandlerですが、致命的なエラーが発生した場合、保存されていないデータが破損する可能性があるため、データの保存は危険であることに注意する必要があります。その場合、正常なデータを上書きしないでください。
nil
super が決して nil を返さない場合でも、objective-c コードが常にイニシャライザをチェックするのはなぜですか? コンベンション、ほとんど。間違いなく、常に nil をチェックすることで、サブクラスを変更する必要なく、スーパークラスが将来失敗条件を追加することが容易になりますが、実際には単なる慣例です。
最後に、初期化子は、スーパークラスの初期化子での失敗をチェックする適切な場所ではありません。回復可能なエラーが発生する可能性がある場合、呼び出し元はエラーをチェックする必要があります。
例:
NSError *error;
FooClass *myFoo = [[FooClass alloc] initWithContentsOfURL:blah error:&error]
if (myFoo == nil) {
// ...
} else {
// ...
}
オブジェクトを初期化するたびに nil をチェックするのはやり過ぎです。error:
これは、引数がある場合、またはメソッドに文書化された回復可能なエラーがある場合にのみ実行する必要があります。
ドキュメントから:-
予想される実行時エラーを含む、その他の種類のエラーについては、nil、NO、NULL、またはその他の型に適した形式のゼロを呼び出し元に返します。これらのエラーの例としては、ファイルの読み取りまたは書き込みができない、オブジェクトを初期化できない、ネットワーク接続を確立できない、コレクション内のオブジェクトを見つけられないなどがあります。エラーに関する補足情報を送信者に返す必要がある場合は、NSError オブジェクトを使用します。NSError オブジェクトは、エラー コード (Mach、POSIX、または OSStatus ドメインに固有の場合があります) やプログラム固有の情報の辞書など、エラーに関する情報をカプセル化します。直接返される負の値 (nil、NO など) は、エラーの主な指標となります。より具体的なエラー情報を伝える場合は、
一般的に言えば、気にせず、nil
伝播させてください。
[super init]
が戻ってきた場合nil
(つまり、新しいオブジェクトをインスタンス化できなかった場合)、何かがひどく混乱しているため、いずれにせよアプリケーションはすぐにクラッシュする可能性があります。
マイケルが提案するように、インスタンス化のたびにチェックするのnil
は面倒で、上記の理由からおそらくまったく役に立たないでしょう。
心配している特定のクラスがあり、できるだけ早く救済したい場合は、計画どおりに進んで例外をスローします。
「復元ポイントの作成」については、可能な限り保存を試みることができますが、シナリオが非常に妥協しているため、成功する保証はありません。
[super init]
20 ギガのメモリ ブロックなどを予約しようとすると、" " は nil をスローする可能性があると思いますが (これは、iOS コーディングを行っている人なら誰もやらないでしょう)、一般に、nil
プロダクション コードでは " " が返されることはめったにありません。
" " が返されることの良い点nil
は、nil オブジェクトにメッセージを送信でき、アプリケーションがクラッシュしないことです。
ただし、オブジェクトをインスタンス化した後は常にチェックをnil
行う必要があります。これは、アプリ (またはユーザー) が回復できないものに深く入り込みすぎないようにするためです。
Apple の「Concepts in Objective C」ドキュメントでは、 「オブジェクトを作成するときは、通常、続行する前に戻り値が nil かどうかを確認する必要があります:」と提案しています。