一.NSParameterAssert官方解釋
Assertions evaluate a condition and, if the condition evaluates to false, call the assertion handler for the current thread, passing it a format string and a variable number of arguments. Each thread has its own assertion handler, which is an object of classNSAssertionHandler.
When invoked, an assertion handler prints an error message that includes method and class names (or the function name). It then raises anNSInternalInconsistencyException exception.
斷言評估一個條件,如果條件為 false ,調(diào)用當(dāng)前線程的斷點句柄。每一個線程有它自已的斷點句柄,它是一個 NSAsserttionHandler 類的對象。當(dāng)被調(diào)用時,斷言句柄打印一個錯誤信息,該條信息中包含了方法名、類名或函數(shù)名。然后,它就拋出一個 NSInternalInconsistencyException 異常。
This macro validates a parameter for an Objective-C method. Simply provide the parameter as the condition argument. The macro evaluates the parameter and, if it is false, it logs an error message that includes the parameter and then raises an exception.
這個宏用于確認一個 Objective-C 的方法的有效性。簡單提供參數(shù)作為條件就行。該宏評估這個參數(shù),如果為 false ,它就打印一個錯誤日志信息,該信息包含了參數(shù)并且拋出一個異常。
Assertions are disabled if the preprocessor macro NS_BLOCK_ASSERTIONS is defined. All assertion macros return void.
如果定義了預(yù)處理宏 NS_BLOCK_ASSERTIONS 斷言就被禁止了。所有的斷點宏都返回 void。
斷言是從經(jīng)典的邏輯學(xué)中借用過來的概念。在邏輯學(xué)中,斷言是對已經(jīng)證明過的命題的陳述。在編程中,斷言是指程序員所做出的關(guān)于應(yīng)用程序在它們所聲明的地方的一些假設(shè)。
當(dāng)用于先驗條件和后驗條件能力范圍內(nèi)時,斷言形成了一種契約,它描述了代碼在執(zhí)行一個方法或函數(shù)的開始和結(jié)束時的狀態(tài)的期望。斷言也能用于加強運行時的條件,為了當(dāng)先驗條件失敗時阻止程序運行。
斷言與單元測試有些類似,它們都定義了代碼將會運行的期望結(jié)果。與單元測試不同的是,斷言存在于程序本身,并且因此被限定在程序的上下文中。因為單元測試是完全獨立的,它們完全有能力通過使用像方法樁和模擬對象等工具隔離并且單獨測試特定的行為。開發(fā)者應(yīng)當(dāng)在應(yīng)該程序中結(jié)合使用合理數(shù)量的斷言和單元測試來測試和定義應(yīng)用程序行為。
二.原理
- Objective-C 用一個面向?qū)ο蟮耐緩交旌狭?C 語言風(fēng)格的斷言宏定義來注入和處理斷言失敗。即:
NSAssertionHandler: - 每個線程擁有它自己的斷言處理器,它是 NSAssertionHandler 類的實例對象。當(dāng)被調(diào)用時,一個斷言處理器打印一條包含方法和類名(或者函數(shù)名)的錯誤信息。然后它拋出一個
NSInternalInconsistencyException異常。
三.延伸
基礎(chǔ)類庫中定義了兩套斷言宏:
NSAssert / NSCAssert
NSParameterAssert / NSCParameterAssert
基礎(chǔ)類庫從語義學(xué)上和功能性上使斷言處理器的 API 在兩個方面區(qū)別開來。
1.第一個區(qū)別在于一般斷言(NSAssert)和參數(shù)化斷言(NSParameterAssert)。方法或函數(shù)應(yīng)當(dāng)在代碼最開始處使用 NSParameterAssert / NSCParameterAssert 來強制輸入的值滿足先驗條件,這是一條金科玉律;其他情況下使用 NSAssert / NSCAssert。
-
2.第二個區(qū)別在于 C 和 Objective-C 的斷言:NSAssert 應(yīng)當(dāng)只用于 Objective-C 環(huán)境中(即方法實現(xiàn)中),而 NSCAssert 應(yīng)當(dāng)只用于 C 環(huán)境中(即函數(shù)中)
- 當(dāng) NSAssert 或 NSParameterAssert 的條件不滿足時,斷言處理器會調(diào)用
-handleFailureInMethod:object:file:lineNumber:description:方法。 - 當(dāng) NSCAssert 或 NSCParameterAssert 的條件不滿足時,斷言處理器會調(diào)用
-handleFailureInFunction:file:lineNumber:description:方法。
- 當(dāng) NSAssert 或 NSParameterAssert 的條件不滿足時,斷言處理器會調(diào)用
值得注意的是,從 Xcode 4.2 開始,發(fā)布構(gòu)建默認關(guān)閉了斷言,它是通過定義 NS_BLOCK_ASSERTIONS 宏實現(xiàn)的。也就是說,當(dāng)編譯發(fā)布版時,任何調(diào)用 NSAssert 等的地方都被有效的移除了。
四.斷言代碼示例
方法一.一般斷言,我們可以這么寫
if (_menuController == nil || _mainController == nil) {
@throw [NSException exceptionWithName: @"LXDNullInstanceException" reason: @"you can not slide view when one or more of menu view and main view is nil" userInfo: nil];
}
// 如果其中一個條件成立,程序崩潰,報下面的錯
// *** Terminating app due to uncaught exception 'LXDNullInstanceException',
reason: 'you can not slide view when one or more of menu view and main view is nil'
方法二:NSAssert
NSAssert(_menuController != nil , @"you can not slide view when one or more of menu view and main view is nil" );
// 方法名 m:118行 報錯描述
// *** Assertion failure in -[LXDSlideManager open], /Users/mac/Downloads/LXDSlideManager.m:118
2016-05-29 17:47:53.655
LXDSlideMenuObjectiveC[77358:4074358]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'you can not slide view when one or more of menu view and main view is nil'
方法三: NSParameterAssert
NSParameterAssert((_menuController != nil));
// 方法名 m:118行 報錯描述
// *** Assertion failure in -[LXDSlideManager open], /Users/mac/Downloads/LXDSlideManager.m:118
2016-05-29 17:47:53.655
LXDSlideMenuObjectiveC[77358:4074358]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'you can not slide view when one or more of menu view and main view is nil'
注意條件書寫不支持邏輯或語法
// 錯誤寫法,不支持邏輯或語法
NSParameterAssert(_menuController != nil || _mainController != nil);
// 錯誤寫法,不支持邏輯或語法
NSAssert(_menuController != nil || _mainController != nil , @"you can not slide view when one or more of menu view and main view is nil" );