iOS開發中斷言的使用—NSAssert()

NSAssert()是一個宏,用于開發階段調試程序中的Bug,通過為NSAssert()傳遞條件表達式來斷定是否屬于Bug,滿足條件返回真值,程序繼續運行,如果返回假值,則拋出異常,并且可以自定義異常描述。
NSAssert()是這樣定義的:

 #define NSAssert(condition, desc)

condition是條件表達式,值為YES或NO;desc為異常描述,通常為NSString。當conditon為YES時程序繼續運行,為NO時,則拋出帶有desc描述的異常信息。NSAssert()可以出現在程序的任何一個位置。

NSAssert和assert 區別
NSAssert和assert都是斷言,主要的差別是assert在斷言失敗的時候只是簡單的終止程序,而NSAssert會報告出錯誤信息并且打印出來.所以只使用NSAssert就好,可以不去使用assert。

NSAssert/NSCAssert
iOS中用的最多的是兩對斷言, NSAssert/NSCAssert 和 NSParameterAssert/NSCparameterAssert. 要知道他們的區別,我們先來看看他們定義.

 #if !defined(NS_BLOCK_ASSERTIONS)
    #if !defined(_NSAssertBody)
    #define NSAssert(condition, desc, ...)  \\\\
    do {              \\\\
    __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \\\\
    if (!(condition)) {       \\\\
    [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \\\\
    object:self file:[NSString stringWithUTF8String:__FILE__] \\\\
    lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \\\\
    }             \\\\
    __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \\\\
    } while(0)
    #endif
    #if !defined(_NSCAssertBody)
    #define NSCAssert(condition, desc, ...) \\\\
    do {              \\\\
    __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \\\\
    if (!(condition)) {       \\\\
    [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \\\\
    file:[NSString stringWithUTF8String:__FILE__] \\\\
    lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \\\\
    }             \\\\
    __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \\\\
    } while(0)
    #endif

從定義可以看出來,前者是適合于ObjectC的方法,_cmd 和 self 與運行時有關. 后者是適用于C的函數。
NSParameterAssert/NSCparameterAssert 兩者的區別也是前者適用于Objective-C的方法,后者適用于C的函數。
實際開發中就用前者就可以了。

NSAssert/NSCAssert 和 NSParameterAssert/NSCparameterAssert 的區別是前者是針對條件斷言, 后者只是針對參數是否存在的斷言, 調試時候可以結合使用,先判斷參數,再進一步斷言,確認原因.

NSAssert的用法

 int a = 1;
    NSCAssert(a == 2, @"a must equal to 2"); //第一個參數是條件,如果第一個參數不滿足條件,就會記錄并打印后面的字符串

運行則會崩潰并在控制臺輸出信息如下:

*** Assertion failure in -[ViewController viewDidLoad](), /Users/yinwentao/Desktop/MYAssert/MYAssert/ViewController.m:32*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'a must equal to 2'

NSParameterAssert的用法

- (void)assertWithPara:(NSString *)str
{
     NSParameterAssert(str); //只需要一個參數,如果參數存在程序繼續運行,如果參數為空,則程序停止打印日志
      //further code ...
}

如果 調用方法 assertWithPara: 傳入參數為空則有如下日志

*** Assertion failure in -[ViewController assertWithPara:], /Users/yinwentao/Desktop/MYAssert/MYAssert/ViewController.m:45*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: str'

日志中的數字是告訴你 第多少行代碼出錯了。

Xcode 已經默認將release環境下的斷言取消了, 免除了忘記關閉斷言造成的程序不穩定. 所以不用擔心 在開發時候大膽使用。

release下是不用擔心的.png.jpeg

自定義NSAssertionHandler
NSAssertionHandler實例是自動創建的,用于處理錯誤斷言。如果 NSAssert和NSCAssert條件評估為錯誤,會向 NSAssertionHandler實例發送一個表示錯誤的字符串。每個線程都有它自己的NSAssertionHandler實例。我們可以自定義處理方法,從而使用斷言的時候,控制臺輸出錯誤,但是程序不會直接崩潰。

#import "MyAssertHandler.h"

@implementation MyAssertHandler

//處理Objective-C的斷言
- (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);
}
//處理C的斷言
- (void)handleFailureInFunction:(NSString *)functionName file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...
{
    NSLog(@"NSCAssert Failure: Function (%@) in %@#%li", functionName, fileName, (long)line);
}

@end

給線程添加處理類

NSAssertionHandler *myHandler = [[MyAssertHandler alloc] init];//給當前的線程[[[NSThread currentThread] threadDictionary] setValue:myHandler forKey:NSAssertionHandlerKey];

自定義NSAssertionHandler后,程序能夠獲得斷言失敗后的信息,但是程序可以繼續運行,不會強制退出程序.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 背景 這幾天被<美國總統大選>和<雙十一>的話題討論著。 第45任美國總統大選,我感覺他們兩誰當選美國總統都挺沒意...
    Dely閱讀 2,099評論 17 21
  • NSAssert()是一個宏,用于開發階段調試程序中的Bug,通過為NSAssert()傳遞條件表達式來斷定是否屬...
    小木___Boy閱讀 42,734評論 5 103
  • 今兒杭州的天氣特別好,被媳婦拉著去西溪濕地的貓空概念書店坐了會兒,小店在一座玻璃房子里,裝修的很清新,四分之一的面...
    戴某DEMO閱讀 434評論 0 0
  • 蝶戀花 清心 憑欄遠望,淺笑如沐暖陽 裙動舞梓桑 懷荷囊依傍 瓠犀發皓齒 雙蛾顰翠眉 紅臉如開蓮 素膚若凝...
    安靜乄晴天閱讀 369評論 1 1