? ? 斷言和先決條件發(fā)是運(yùn)行時(shí)發(fā)生的檢測滚局。使用它們可以確保在執(zhí)行后面的代碼之前已經(jīng)滿足了條件叁温。如果斷言或者先決條件中的值是true,代碼像原來一樣繼續(xù)執(zhí)行核畴。如果條件是false膝但,程序當(dāng)前的狀態(tài)就是無效的,代碼會(huì)結(jié)束執(zhí)行谤草,app也會(huì)停止運(yùn)行跟束。
? ? 使用斷言和先決條件來表現(xiàn)出你編寫代碼的時(shí)候做的假設(shè)和希望,并讓他們成為你代碼的一部分丑孩。斷言幫助你在開發(fā)過程中發(fā)現(xiàn)錯(cuò)誤和不合適的假設(shè)冀宴。先決條件幫助你在生產(chǎn)環(huán)境下檢測問題。
? ? 除了在運(yùn)行時(shí)驗(yàn)證你的期望温学,斷言和先決條件也可以成為代碼中的文檔略贮,這很有用。和上一章討論的錯(cuò)誤處理不一樣,斷言和先決條件不是用來處理可恢復(fù)的或者預(yù)期會(huì)發(fā)生的錯(cuò)誤的逃延。因?yàn)楫?dāng)一個(gè)斷言或者先決條件失敗了览妖,那么程序當(dāng)前的狀態(tài)就是無效的,沒有辦法捕獲一個(gè)發(fā)生了錯(cuò)誤的斷言揽祥。
? ? 使用斷言或者先決條件讽膏,不是為了把代碼設(shè)計(jì)成不會(huì)出現(xiàn)不符合條件的樣子。使用它們加強(qiáng)數(shù)據(jù)和狀態(tài)的有效性使你可以預(yù)見到app在出現(xiàn)不可用狀態(tài)的時(shí)候會(huì)導(dǎo)致結(jié)束拄丰,也使問題更加容易被調(diào)試府树。只要偵測到異常就結(jié)束執(zhí)行也可以最小化無效的狀態(tài)帶來的危害。
? ? 斷言和先決條件的不同之處在于它們檢測的時(shí)機(jī)不一樣:斷言只在調(diào)試模式中檢測料按,先決條件在調(diào)試模式和產(chǎn)品模式都會(huì)檢測奄侠。在產(chǎn)品模式下,斷言中的條件不會(huì)被檢測载矿,也就是說在開發(fā)過程中遭铺,無論使用多少斷言,都不會(huì)影響最后的產(chǎn)品的性能恢准。
使用斷言調(diào)試(Debugging with Assertions)
? ? 我們通過調(diào)用Swift標(biāo)準(zhǔn)庫的assert(_:_:file:line:)方法來書寫斷言魂挂。傳入一個(gè)結(jié)果是true或者false的表達(dá)式和一個(gè)當(dāng)條件是false的時(shí)候要展示的信息,比如:
? ??????let age = -3
????????assert(age >= 0, "A person's age can't be less than zero.")
????????// 這個(gè)斷言會(huì)失敗馁筐, 應(yīng)該 -3 ?>= 0 結(jié)果是false.
? ? 這個(gè)例子中涂召,如果 age>=0是true,也就是age如果是一個(gè)非負(fù)數(shù),代碼會(huì)繼續(xù)執(zhí)行敏沉。如果age的值是一個(gè)負(fù)數(shù)果正,在上面的代碼中,age>=0就是false盟迟,然后斷言會(huì)失敗秋泳,應(yīng)用會(huì)結(jié)束。
? ? 你也可以省略斷言的信息攒菠,比如迫皱,只是需要重復(fù)檢查條件:
? ??????assert(age >= 0)
? ? 如果代碼中已經(jīng)檢查了條件,你可以使用assertionFailure(_:file:line:)函數(shù)表明這個(gè)斷言失敗了辖众,比如:
? ??????if age > 10 {
? ? ????????????print("You can ride the roller-coaster or the ferris wheel.")
????????????} else if age > 0 {
????????????? ? print("You can ride the ferris wheel.")
????????????} else {
????????????? ? assertionFailure("A person's age can't be less than zero.")
????????}
強(qiáng)制執(zhí)行先決條件(Enforcing Preconditions)
? ? 當(dāng)條件有可能是false的情況下卓起,使用先決條件,但是需要確定只有當(dāng)條件是true的時(shí)候你的代碼才會(huì)繼續(xù)執(zhí)行凹炸。例如戏阅,使用先決條件判斷一個(gè)下標(biāo)是不是越界了,或者檢查入?yún)⑹遣皇怯行А?/p>
? ? 可以通過調(diào)用precondition(_:_:file:line:)函數(shù)書寫先決條件啤它。傳入一個(gè)結(jié)果是true或者false的表達(dá)式和一個(gè)當(dāng)條件是false的時(shí)候要展示的信息奕筐,比如:
?????????// In the implementation of a subscript...
? ? ? ? //引用于subscript的實(shí)現(xiàn)
????????precondition(index > 0, "Index must be greater than zero.")
? ? 你可以調(diào)用preconditionFailure(_:file:line:)函數(shù)來表明先決條件失敗了舱痘,例如,在一個(gè)swift語句的defaultcase里面离赫,所有有效的數(shù)據(jù)應(yīng)該在switch其他的case里面已經(jīng)被處理了芭逝,那么在defaultcase里面就可以使先決條件失敗。
NOET:如果編譯器在不檢查的模式(-Ounchecked)笆怠,先決條件不會(huì)被檢查铝耻。編譯器會(huì)假設(shè)所有的先決條件都是成功的誊爹。因此,編譯器會(huì)優(yōu)化你的代碼蹬刷。然而fatalError(_:file:line:)函數(shù)總是會(huì)停止執(zhí)行代碼,不理會(huì)是否有優(yōu)化的設(shè)置频丘。在編寫Demo或者開發(fā)的早期办成,可以為一些尚未完成的功能創(chuàng)造一些占位方法,并用fatalError("Unimplemented")作為占位方法的實(shí)現(xiàn)搂漠。因?yàn)楹蛿嘌曰蛘呦葲Q條件不一樣迂卢,致命的錯(cuò)誤是不會(huì)被優(yōu)化的,所以你可以確定當(dāng)碰到一些沒有實(shí)現(xiàn)的占位方法桐汤,程序總會(huì)因?yàn)榕龅街旅腻e(cuò)誤而停止運(yùn)行而克。