web-dev-qa-db-ja.com

NSAssertのポイントは何ですか?

私はこれを尋ねる必要があります:私が認識する唯一のことは、アサーションが失敗すると、アプリがクラッシュするということです。 NSAssertを使用する理由はそれですか?または、他に何の利点がありますか? NS-1

153
HelloMoon

アサートとは、値が本来あるべきものであることを確認することです。アサーションが失敗した場合、何か問題が発生したため、アプリが終了します。 assertを使用する理由の1つは、渡されるパラメータの1つが正確に何らかの値(または値の範囲)ではない場合、動作しないか非常に悪い副作用を引き起こす関数がある場合ですその値が期待どおりであることを確認してください。そうでない場合、何かが本当に間違っているので、アプリは終了します。アサートは、デバッグ/単体テストに非常に役立ちます。また、ユーザーが「悪」なことをするのを止めるフレームワークを提供する場合にも役立ちます。

298
Daniel

NSAssertとは実際には話せませんが、Cのassert()と同様に機能すると思います。

assert()は、コードでセマンティックコントラクトを実施するために使用されます。それはどういう意味ですか、あなたは尋ねますか?

さて、それはあなたが言ったようです:-1を決して受け取らない関数がある場合、assert()にそれを強制させることができます:

 void gimme_positive_ints(int i){
 assert(i> 0); 
} 

これで、エラーログ(またはSTDERR)に次のような内容が表示されます。

アサーションi> 0が失敗しました:ファイルexample.c、行2 

そのため、不正な入力を防ぐだけでなく、有用で標準的な方法でログに記録します。

ああ、少なくともCでは、assert()はマクロだったので、リリースコードでassert()をノーオペレーションとして再定義できます。 NSAssertの場合(またはassert()の場合もあります)かどうかはわかりませんが、これらのチェックをコンパイルすることは非常に役に立ちました。

20
Mando Escamilla

上記の全員の発言とは別に、NSAssert()のデフォルトの動作は(Cのassert()とは異なり)キャッチして処理できる例外をスローすることです。たとえば、Xcodeはこれを行います。

17
Jens Ayton

NSAssertは、単にアプリをクラッシュさせるだけではありません。クラス、メソッド、およびアサーションが発生した行を示します。 NS_BLOCK_ASSERTIONSを使用して、すべてのアサーションを簡単に無効にすることもできます。したがって、デバッグに適しています。一方、NSExceptionをスローすると、アプリがクラッシュするだけです。また、例外の場所についても通知せず、簡単に無効にすることもできません。以下の画像の違いをご覧ください。

NSAssert documentation が示すように、アサーションも例外を発生させるため、アプリがクラッシュします。

アサーションハンドラーが呼び出されると、メソッド名とクラス名(または関数名)を含むエラーメッセージが出力されます。次に、NSInternalInconsistencyException例外が発生します。

NSAssert:

Logs after an assertion

NSException:

Logs after an exception

明確にするために、誰かが言及したが完全には説明されていないように、カスタムコードを作成するだけでなく、アサートを使用して使用する理由(たとえば、ifを実行し、不正なデータに対して例外を発生させる)は、実稼働アプリケーションに対してアサートを無効にする必要があることです。

開発およびデバッグ中に、エラーをキャッチするためにアサートが有効になります。アサートがfalseと評価されると、プログラムは停止します。しかし、実動用にコンパイルする場合、コンパイラはアサーションコードを省略し、実際にプログラムをより速く実行します。それまでに、うまくいけば、すべてのバグを修正できました。実稼働中にプログラムにまだバグがある場合(アサーションが無効になり、プログラムがアサーションを「スキップ」する場合)、プログラムはおそらく他のポイントでクラッシュします。

NSAssertのヘルプから:「プリプロセッサマクロNS_BLOCK_ASSERTIONSが定義されている場合、アサーションは無効になります。」そのため、配布ターゲットにマクロを配置してください[のみ]。

9
Ohad Kravchick

NSAssert(およびそれに相当するstdlib assert)は、開発中のプログラミングエラーを検出するためのものです。本番(リリース済み)アプリケーションで失敗するアサーションを使用しないでください。したがって、正の引数を必要とするメソッドに負の数を決して渡さないと断言できます。テスト中にアサーションが失敗する場合、バグがあります。ただし、渡された値がユーザーによって入力された場合、実稼働環境でのアサーションに依存するのではなく、入力の適切な検証を行う必要があります(リリースビルドに対してNSAssert*を無効にする#defineを設定できます。

6
Barry Wark

実行時チェックとは別に、アサートプログラミングは、契約によってコードを設計するときに使用される重要な機能であることを指摘する価値があります。

アサーションおよび契約ごとの設計のテーマに関する詳細は、以下を参照してください。

アサーション(ソフトウェア開発)

契約による設計

アサーションを使用したプログラミング

契約による設計、例[ペーパーバック]による

3
Boon

アサーションは通常、特定のメソッドまたはロジックの一部の意図された使用を強制するために使用されます。ゼロより大きい2つの整数の合計を計算するメソッドを書いていたとしましょう。メソッドが常に意図したとおりに使用されていることを確認するには、おそらくその条件をテストするアサートを配置します。

簡単な答え:コードは意図したとおりにのみ使用されることを強制します。

3
Lounges

彼の質問に完全に答えるために、あらゆるタイプのアサートのポイントは、デバッグを支援することです。エラーをソースでキャッチし、クラッシュが発生したときにデバッガでエラーをキャッチする方がより価値があります。

たとえば、特定の範囲の値を期待する関数に値を渡すことができます。関数は後で使用するために値を保存し、後で使用するとアプリケーションがクラッシュする場合があります。このシナリオで見られる呼び出しスタックは、不正な値のソースを表示しません。誰が悪い値を渡しているのか、そしてその理由を調べるには、悪い値をキャッチする方が良いでしょう。

2
Robert Hawkey