私が認識しているのは、アサーションが失敗するとアプリがクラッシュするということだけです。それがNSAssertを使用する理由ですか?またはそれの他に何の利点がありますか?そして、パラメーターとして-1を受け取ることはないが、-0.9または-1.1を受け取る可能性がある関数のように、コードで行う仮定のすぐ上にNSAssertを配置するのは正しいですか?
10 に答える
アサートとは、値が想定どおりであることを確認することです。アサーションが失敗した場合、それは何かがうまくいかなかったことを意味し、アプリは終了します。assertを使用する理由の1つは、渡されたパラメーターの1つが正確に値(または値の範囲)ではない場合に動作しない、または非常に悪い副作用を引き起こす関数がある場合に、assertを作成できるようにすることです。値が期待どおりであることを確認してください。そうでない場合は、何かが本当に間違っているため、アプリは終了します。アサートは、デバッグ/単体テストに非常に役立ちます。また、ユーザーが「邪悪な」ことをするのを防ぐためのフレームワークを提供する場合にも役立ちます。
NSAssertと実際に話すことはできませんが、Cのassert()と同様に機能すると思います。
assert()は、コードにセマンティックコントラクトを適用するために使用されます。それはどういう意味ですか?
さて、あなたが言ったように:-1を決して受け取らない関数がある場合、assert()にそれを強制させることができます:
void gimme_positive_ints(int i){ assert(i> 0); }
そして今、あなたはエラーログ(またはSTDERR)にこのようなものを見るでしょう:
アサーションi>0が失敗しました:ファイルexample.c、2行目
したがって、潜在的に不良な入力から安全に保護するだけでなく、有用で標準的な方法でそれらをログに記録します。
ああ、少なくともCではassert()はマクロだったので、リリースコードでassert()をno-opとして再定義できます。NSAssert(またはassert())の場合かどうかはわかりませんが、これらのチェックをコンパイルすることは非常に便利でした。
NSAssert
アプリをクラッシュさせるだけではありません。クラス、メソッド、およびアサーションが発生した行を示します。NS_BLOCK_ASSERTIONSを使用して、すべてのアサーションを簡単に非アクティブ化することもできます。したがって、デバッグにより適したものになります。一方、NSException
のみを投げるとアプリがクラッシュします。また、例外の場所についても通知しません。また、簡単に無効にすることもできません。下の画像の違いをご覧ください。
NSAssertのドキュメントに記載されているように、アサーションでも例外が発生するため、アプリがクラッシュします。
アサーションハンドラーが呼び出されると、メソッド名とクラス名(または関数名)を含むエラーメッセージが出力されます。次に、NSInternalInconsistencyException例外が発生します。
NSAssert:
NSException:
誰もが上で言ったこととは別に、NSAssert()
(Cとは異なりassert()
)のデフォルトの動作は例外をスローすることであり、これをキャッチして処理することができます。たとえば、Xcodeはこれを行います。
明確にするために、誰かが言及したが完全には説明されていないように、カスタムコードを作成するだけでなくassertを使用して使用する理由(たとえば、ifを実行し、不良データの例外を発生させる)は、本番アプリケーションではassertを無効にする必要があるためです。
開発およびデバッグ中に、エラーをキャッチできるようにアサートが有効になります。アサートがfalseと評価されると、プログラムは停止します。ただし、本番用にコンパイルする場合、コンパイラーはアサーションコードを省略し、実際にプログラムをより高速に実行します。それまでに、うまくいけば、すべてのバグを修正しました。本番環境でプログラムにまだバグがある場合(アサーションが無効になっていて、プログラムがアサーションを「スキップ」する場合)、プログラムは別の時点でクラッシュする可能性があります。
NSAssertのヘルプから:「プリプロセッサマクロNS_BLOCK_ASSERTIONSが定義されている場合、アサーションは無効になります。」したがって、マクロを配布ターゲットに配置するだけです[のみ]。
NSAssert
(およびそれに相当するstdlib assert
)は、開発中のプログラミングエラーを検出するためのものです。本番(リリース済み)アプリケーションで失敗するアサーションは絶対に使用しないでください。したがって、正の引数を必要とするメソッドに負の数を渡すことは絶対にないと主張するかもしれません。テスト中にアサーションが失敗した場合は、バグがあります。ただし、渡された値がユーザーによって入力された場合は、本番環境でのアサーションに依存するのではなく、入力の適切な検証を行う必要があります(を無効にするリリースビルドの#defineを設定できますNSAssert*
。
アサーションは通常、特定のメソッドまたはロジックの意図された使用を強制するために使用されます。ゼロより大きい2つの整数の合計を計算するメソッドを作成しているとしましょう。メソッドが常に意図したとおりに使用されていることを確認するために、おそらくその条件をテストするアサーションを配置します。
簡単な答え:彼らはあなたのコードが意図されたようにのみ使用されることを強制します。
実行時のチェックとは別に、アサーションプログラミングは、コントラクトによってコードを設計するときに使用される重要な機能であることを指摘する価値があります。
契約によるアサーションと設計の主題に関する詳細は、以下にあります。
彼の質問に完全に答えるために、あらゆるタイプのアサーションのポイントは、デバッグを支援することです。それらのソースでエラーをキャッチし、クラッシュの原因となったときにデバッガーでエラーをキャッチする方がより価値があります。
たとえば、特定の範囲の値を期待する関数に値を渡すことができます。この関数は、後で使用するために値を保存する場合があり、後で使用するとアプリケーションがクラッシュします。このシナリオで見られるコールスタックは、不正な値の原因を示していません。誰が悪い値を渡しているのか、そしてその理由を見つけるために、悪い値をキャッチする方が良いでしょう。
NSAssert
条件に一致するとアプリがクラッシュします。条件と一致しない場合、次のステートメントが実行されます。以下のEXを探してください:
私はアプリを作成して、次のタスクが何であるかをテストしますNSAssert
。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self testingFunction:2];
}
-(void)testingFunction: (int)anNum{
// if anNum < 2 -> the app will crash
// and the NSLog statement will not execute
// that mean you cannot see the string: "This statement will execute when anNum < 2"
// into the log console window of Xcode
NSAssert(anNum >= 2, @"number you enter less than 2");
// If anNum >= 2 -> the app will not crash and the below
// statement will execute
NSLog(@"This statement will execute when anNum < 2");
}
私のコードでは、アプリはクラッシュしません。テストケースは次のとおりです。
anNum
> = 2->アプリはクラッシュせず、ログ文字列を確認できます: "このステートメントは、出力ログコンソールウィンドウにanNum<2"の場合に実行されますanNum
<2->アプリがクラッシュし、ログ文字列が表示されない:"このステートメントは、anNum<2の場合に実行されます"