斷言(assertion)是指在開發(fā)期間使用的、讓程序在運(yùn)行時(shí)進(jìn)行自檢的代碼(通常是一個(gè)子程序或宏)。斷言為真,則表明程序運(yùn)行正常,而斷言為假,則意味著它已經(jīng)在代碼中發(fā)現(xiàn)了意料之外的錯(cuò)誤。斷言對(duì)于大型的復(fù)雜程序或可靠性要求極高的程序來(lái)說(shuō)尤其有用。
在開發(fā)階段,代碼極可能包含缺陷,也許是處理外部數(shù)據(jù)的程序考慮的不夠周全,也許是調(diào)用系統(tǒng)內(nèi)部子程序的代碼存在錯(cuò)誤,造成子程序調(diào)用失敗。這個(gè)時(shí)候,斷言就可以發(fā)揮作用,用來(lái)確診到底是那部分出現(xiàn)了問(wèn)題而導(dǎo)致子程序調(diào)用失敗。在清理了所有缺陷之后,內(nèi)外有別的信用體系就建立起來(lái)。等到發(fā)行版時(shí)候,這些斷言就應(yīng)該沒(méi)有存在必要。
在iOS開發(fā)中,可以使用宏NSAssert()在程序中進(jìn)行斷言處理。NSAssert()使用正確,可以幫助開發(fā)者盡快定位bug。開發(fā)者沒(méi)有必要在應(yīng)用程序的每個(gè)版本中都進(jìn)行斷言檢查,這是因?yàn)榇蠖鄶?shù)項(xiàng)目都是有兩個(gè)版本:Debug版和Release版。在Debug版中,開發(fā)者希望所有的斷言都檢查到,而在Release版中,往往都是禁用斷言檢查的。設(shè)置Release版本中禁用斷言的方法如下:
在Build Settings菜單,找到Preprocessor Macros項(xiàng),Preprocessor Macros項(xiàng)下面有一個(gè)選擇,用于程序生成配置:Debug版和Release版。選擇 Release項(xiàng),設(shè)置NS_BLOCK_ASSERTIONS,不進(jìn)行斷言檢查。如下圖所示。

下面,我們?cè)谝粋€(gè) 打印名字的函數(shù)里面,加入斷言,以使程序在發(fā)現(xiàn)輸入的名字為空時(shí),拋出異常。
- (void)printMyName:(NSString *)myName
{
NSAssert(myName != nil, @"名字不能為空!");
NSLog(@"My name is %@.",myName);
}
當(dāng)傳給函數(shù)的參數(shù)(myName)為空時(shí),斷言將被執(zhí)行,程序Crash,并打印出斷言中的描述信息。本例中,在控制臺(tái)打印出了如下的日志:
NSAssert[1268:a0b] *** Assertion failure in -[ViewController printMyName:]
NSAssert/NSAssert/ViewController.m:38
2013-11-21 13:56:01.927 NSAssert[1268:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '名字不能為空!'
斷言告訴我們,傳入的參數(shù)不能為空,通過(guò)這個(gè)報(bào)錯(cuò)很容易就能確定錯(cuò)誤發(fā)生的原因及位置。
如果,我們傳入非空的參數(shù),則程序會(huì)正確打印出傳入的名字:
My name is UnivCore.
下面,我們將測(cè)試程序設(shè)置為Release版本,依據(jù)之前的設(shè)定,即使當(dāng)傳入的參數(shù)為空時(shí),斷言也不會(huì)被執(zhí)行。設(shè)置為Release版本的方法如下:
依次點(diǎn)擊Product->Scheme->Edit Scheme...(也可以直接按快捷鍵command + shift + ,),選擇Run 項(xiàng),然后在Info面板上修改Build Configuration為Release,就可以將當(dāng)前的生成配置改為Release。然后,生成并運(yùn)行程序,就會(huì)生成Release版本的程序。注意,對(duì)于Archive 項(xiàng),默認(rèn)的生成配置就是Release。

此時(shí),我們?cè)龠\(yùn)行程序,程序會(huì)打印如下語(yǔ)句:
My name is (null).
這說(shuō)明,斷言代碼沒(méi)有運(yùn)行。