NSAssert和NSParameterAssert在開發環境中經常被使用,調試和驗證代碼參數的完整性,斷言為真,則表明程序運行正常,而斷言為假,則意味著它已經在代碼中發現了意料之外的錯誤。xCode中的斷言在Debug模式默認是開啟的,Realse版本中是禁用的.
基礎斷言
基礎類庫中了兩種斷言,NSAssert和NSParameterAssert是OC斷言,NSCAssert和NSCParameterAssert是C語言斷言。先來看一下NSAssert定義:
<pre><code>The NSAssert macro evaluates the condition and serves as a front end to the assertion handler. Each thread has its own assertion handler, which is an object of class NSAssertionHandler. When invoked, an assertion handler prints an error message that includes the method and class names (or the function name). It then raises an NSInternalInconsistencyException exception. If condition evaluates to NO, the macro invokes handleFailureInMethod:object:file:lineNumber:description: on the assertion handler for the current thread, passing desc as the description string. This macro should be used only within Objective-C methods. Assertions are disabled if the preprocessor macro NS_BLOCK_ASSERTIONS is defined. **Important:Important** Do not call functions with side effects in the condition parameter of this macro. The condition parameter is not evaluated when assertions are disabled, so if you call functions with side effects, those functions may never get called when you build the project in a non-debug configuration. **Note:Note** Not all release configurations disable assertions by default.
</code></pre>
NSParameterAssert的定義:
<pre>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 class NSAssertionHandler. When invoked, an assertion handler prints an error message that includes method and class names (or the function name). It then raises an NSInternalInconsistencyException exception. 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. Assertions are disabled if the preprocessor macro NS_BLOCK_ASSERTIONS is defined. All assertion macros return void. **Important:Important** Do not call functions with side effects in the condition parameter of this macro. The condition parameter is not evaluated when assertions are disabled, so if you call functions with side effects, those functions may never get called when you build the project in a non-debug configuration. **Note:Note** Not all release configurations disable assertions by default.
</pre>
兩者的定義類似,大概意思就是如果是false就會調用當前線程Assertion Hanlder進行處理,非Debug模式下可能所有的斷言都不會調用,最后一句很重要,并不是所有的發布配置會禁用斷言,如果想看斷言是否禁用,需要看一下設置:

簡單測試:
<pre><code>`
NSString *result=@"中山郎";
NSInteger count=10;
NSAssert(count>10, @"總數必須大于10");
NSLog(@"斷言執行之后");
?
</code></pre> 崩潰信息: <pre><code>
** FECategory[23811:248235] *** Assertion failure in -[ViewController setupAssert], /ViewController.m:45**
** FECategory[23811:248235] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '****總數必須大于****10'**`</code></pre>
NSAssertionHandler
NSAssert異常處理的時候默認是NSAssertionHandler處理的,不過我們可以自定自己的Handler,實現兩個方法:
<pre><code>`
- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(nullable NSString *)format,... NS_FORMAT_FUNCTION(5,6);
- (void)handleFailureInFunction:(NSString *)functionName file:(NSString *)fileName lineNumber:(NSInteger)line description:(nullable NSString *)format,... NS_FORMAT_FUNCTION(4,5);`</code></pre>
handleFailureInMethod處理OC方法中的斷言,handleFailureInFunction處理C函數中的斷言
自定義繼承自NSAssertionHandler的類FEAssertionHandler:
<pre><code>`
@implementation FEAssertionHandler
-(void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...{
NSLog(@"FlyElephant-FEAssertionHandler: Method %@ for object %@ in %@--line:%li", NSStringFromSelector(selector), object, fileName, (long)line);
}
-(void)handleFailureInFunction:(NSString *)functionName file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...{
NSLog(@"FlyElephant-FEAssertionHandler:Function (%@) in %@--line:%li", functionName, fileName, (long)line);
}
@end</code></pre> AppDelegate中設置斷言處理: <pre><code>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
FEAssertionHandler *hanlder=[[FEAssertionHandler alloc]init];
[[[NSThread currentThread] threadDictionary] setValue:hanlder forKey:NSAssertionHandlerKey];
return YES;
}