NSAssert()是一個(gè)宏,用于開發(fā)階段調(diào)試程序中的Bug,通過為NSAssert()傳遞條件表達(dá)式來斷定是否屬于Bug,滿足條件返回真值,程序繼續(xù)運(yùn)行,如果返回假值,則拋出異常,并且可以自定義異常描述。
NSAssert是一系列宏,主要方法有以下幾個(gè)
/** `condition`條件語句,當(dāng)條件為假時(shí),程序會(huì)在這一行崩潰并且打印`desc`信息 */
#define NSAssert(condition, desc, ...)
#define NSAssert1(condition, desc, arg1)
...
#define NSAssert5(condition, desc, arg1, arg2, arg3, arg4, arg5)
#define NSParameterAssert(condition) NSAssert((condition), @"Invalid parameter not satisfying: %@", @#condition)
------------------------------------------------
/** `NSCAssert`含義和`NSAssert`相同 */
#define NSCAssert(condition, desc, ...)
#define NSCAssert1(condition, desc, arg1)
...
#define NSCAssert5(condition, desc, arg1, arg2, arg3, arg4, arg5)
#define NSCParameterAssert(condition) NSCAssert((condition), @"Invalid parameter not satisfying: %@", @#condition)
// 注意,NSAssert 適用于OC的斷言,而 NSCAssert 適用于C函數(shù)的斷言
關(guān)于NSAssert和assert 區(qū)別
NSAssert和assert都是斷言,主要的差別是assert在斷言失敗的時(shí)候只是簡(jiǎn)單的終止程序,而NSAssert會(huì)報(bào)告出錯(cuò)誤信息并且打印出來.所以只使用NSAssert就好,可以不去使用assert
NSAssert/NSCAssert 和 NSParameterAssert/NSCparameterAssert 的區(qū)別
前者是針對(duì)條件斷言, 后者只是針對(duì)參數(shù)是否存在的斷言, 調(diào)試時(shí)候可以結(jié)合使用,先判斷參數(shù),再進(jìn)一步斷言,確認(rèn)原因
NSAssert 使用
NSInteger i = 10;
// 第一個(gè)參數(shù)是條件,如果條件為假,就會(huì)記錄并打印后面的字符串
NSAssert(i > 10, @"i 實(shí)際上 <= 10");
運(yùn)行程序崩潰并且看到打印錯(cuò)誤信息:
*** Assertion failure in -[ViewController viewDidLoad], /Users/ZFeng/Desktop/temp/temp/
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'i 實(shí)際上 <= 10'
NSParameterAssert 使用
- (void)testNSParameterAssert:(NSString *)str
{
// 參數(shù)存在程序繼續(xù)運(yùn)行,如果參數(shù)為空,則程序停止打印日志
NSParameterAssert(str);
// do somthing
}
我們調(diào)用方法并且給str傳一個(gè)空值:
[self testNSParameterAssert:nil];
運(yùn)行程序崩潰并且看到打印錯(cuò)誤信息:
*** Assertion failure in -[ViewController testNSParameterAssert:], /Users/ZFeng/Desktop/temp/temp/ViewController.m:28
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: str'
NSAssertionHandler 斷言處理
NSAssertionHandler實(shí)例是自動(dòng)創(chuàng)建的,用于處理錯(cuò)誤斷言。如果 NSAssert和NSCAssert條件評(píng)估為錯(cuò)誤,會(huì)向 NSAssertionHandler實(shí)例發(fā)送一個(gè)表示錯(cuò)誤的字符串。每個(gè)線程都有它自己的NSAssertionHandler實(shí)例。
我們可以自定義處理方法,從而使用斷言的時(shí)候,控制臺(tái)輸出錯(cuò)誤,但是程序不會(huì)直接崩潰。
// 處理C的斷言
- (void)handleFailureInFunction:(NSString *)functionName file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...
{
NSLog(@"NSCAssert Failure: Function (%@) in %@#%li", functionName, fileName, (long)line);
}
// 處理OC的斷言
- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...
{
NSLog(@"NSAssert Failure: Method %@ for object %@ in %@#%li", NSStringFromSelector(selector), object, fileName, (long)line);
}
使用我們自己的斷言進(jìn)行處理:
// 自定義的斷言處理
NSAssertionHandler *myHandler = [[ZFAssertionHandler alloc] init];
[[[NSThread currentThread] threadDictionary] setValue:myHandler forKey:NSAssertionHandlerKey];
自定義NSAssertionHandler后,程序能夠獲得斷言失敗后的信息,但是程序可以繼續(xù)運(yùn)行,不會(huì)強(qiáng)制退出程序。
Xcode 已經(jīng)默認(rèn)將release環(huán)境下的斷言取消了, 免除了忘記關(guān)閉斷言造成的程序不穩(wěn)定. 所以不用擔(dān)心 在開發(fā)時(shí)候大膽使用。
