斷言(assertion)在Cocoa 開發(fā)里一般用來檢查輸入?yún)?shù)是否滿足一定條件联予,并對其進行“論斷”示姿。這是一個編碼世界中的哲學(xué)問題,我們代碼的使用者(可能是別的程序猿桐早,也有可能是未來的自己)很難做到在不知道實現(xiàn)細(xì)節(jié)的情況下對自己的輸入進行限制癣缅。大多數(shù)時候編譯器可以幫助我們進行輸入類型的檢查,但是如果代碼需要在特定的輸入條件下才能正確運行的話哄酝,這種更細(xì)致的條件就難以控制了友存。在超過邊界條件的輸入情況下,我們的代碼可能無法正確工作陶衅,這就需要我們在代碼實現(xiàn)中進行額外工作屡立。
一種很容易想到的做法是在方法內(nèi)部使用if這樣的條件控制來檢測輸入,如果遇到無法繼續(xù)的情況搀军,就提前返回或者拋出錯誤膨俐。但是這樣的做法無疑增加了API使用的復(fù)雜度,也導(dǎo)致了很多運行時的額外開銷罩句。對于像判定輸入是否滿足某種條件的運用情景焚刺,我們有更好的選擇,那就是斷言门烂。
Swift 為我們提供了一系列的assert方法來使用斷言乳愉,其中最常用的一個是:
fun assert(@autoclosure condition: () -> Bool,
@autoclosure _ message: () -> String = default,
file: StaticString = default,
line: UInt = default)
在使用時,最常見的情況是給定條件和一個簡單的說明屯远。舉一個在溫度轉(zhuǎn)換時候的例子蔓姚,我們想要把攝氏溫度轉(zhuǎn)為開爾文溫度的時候,因為絕對零度永遠(yuǎn)不能達到慨丐,所以我們不可能接受一個小于-273.15攝氏溫度作為輸入:
func convertTokelvin(# celsius: Double) -> Double{
assert(celsius > absoluteZeroInCelsius,"輸入的攝氏溫度不能低于絕對零度")
return celsius - absoluteZeroInCelsius
}
let roomTemperature = convertToKelvin(celsius: 27)
// roomTemperature = 300.15
let tooCold = convertToKelvin(celsius: -300)
// 運行時錯誤
// assertion failed:
// 輸入的攝氏溫度不能低于絕對零度: file{YOUR_FILE_PATH}, line {LINE_NUMBER}
在遇到無法處理輸入時坡脐,運行會產(chǎn)生錯誤,保留堆棧房揭,并拋出我們預(yù)設(shè)的信息备闲,用來提醒調(diào)用這段代碼的用戶晌端。
斷言的另一個優(yōu)點是它是一個開放時的特性,只有在Debug編譯的時候有效浅役,而在運行時是不被編譯執(zhí)行的斩松,因此斷言并不會消耗運行時的性能。這些特點使得斷言成為面向程序員的在調(diào)試開發(fā)階段非常適合的調(diào)試判斷觉既,而在代碼發(fā)布的時候惧盹,我們也不需要刻意去將這些斷言手動清理掉,非常方便瞪讼。
雖然默認(rèn)情況下只在 Release 的情況下斷言才會被禁用钧椰,但是有時候我們可能處于某些目的希望斷言在調(diào)試開發(fā)時也暫時停止工作,或者是在發(fā)布版本中也繼續(xù)有效符欠。我們可以通過顯式的添加編譯標(biāo)記達到這個目的嫡霞。在對于target 的Build Setting中,我們在Swift Compiler - Custom Flags 中的Other Swift Flags 中添加 -assert-config Debug 來強制啟用斷言希柿,或者-assert-config Release 來強制禁用斷言诊沪。當(dāng)然,除非有充足的理由曾撤,否則并不建議做這樣的改動端姚。如果我們需要在Release發(fā)布時在無法繼續(xù)時將程序強行終止的話,應(yīng)該選擇使用fatalError挤悉。