Swift 2.0 異常處理
WWDC 2015 宣布了新的 Swift 2.0 . 這次重大更新給 Swift 提供了新的異常處理方法。這篇文章會主要圍繞這個方面進行討論。
如何建造異常類型?
在 iOS 開發當中,我們會面對很多異常處理。在 Cocoa Touch 中我們使用 NSError 來進行異常處理。在新的 Swift 2.0 中,我們可以使用新的 ErrorType protocol。
在 Swift 中, enum 是最好的方法建立屬于你自己的異常類型,你只要在你的 enum 中確認新的 ErrorType。
enum MyError: ErrorType { case NotExist case OutOfRange }
如何拋出異常
在拋出異常之前,我們需要在函數或方法的返回箭頭 -> 前使用 throws 來標明將會拋出異常
func myMethodRetrunString() throws -> String // No return, we can just add throws in the end func myMethodRetrunNothing() throws
聲明之后, 我們需要在函數或者方法里扔出異常,很簡單使用throw 就可以了
func myMethod() throws //... // item is an optional value guard let item = item else { // need throws the error out throw MyError.NotExist } // do with item }
上面這段代碼使用了 guard 來進行unwrap optional value。這是 Swift 2.0 提供的一個新的方法。
Guard
在 Haskell, Erlang 等語言中早已存在 guard, 在這里有更多關于它的介紹 。
guard 翻譯過來可以理解為守護,守衛。
在 Swift 中,guard 有點像 if 但是他們有兩個非常重要的區別
-
guard 必須強制有 else 語句
</li> -
只有在 guard 審查的條件成立,guard 之后的代碼才會運行 (像守衛一樣,條件不符就不讓過去)。
</li> </ul>guard 中的 else 只能執行轉換語句,像 return, break, continue 或者 throws 當然你也可以在這里返后一個函數或者方法。
值得注意的是,guard的使用會提高你代碼的可讀性,但是也代表你的代碼的執行會有非常明確的順序性,這一點需要開發者們留心處理。
雖然我們在異常處理中提到了 guard 但是不代表它只能在異常處理中使用。它具有廣泛的適用性,或許過陣子我會專門為 guard的使用寫篇文章。
如何獲取并處理異常?
上文講述了如何建造拋出異常,獲取和處理異常就變得很簡單了。使用 do-catch 機制。
do { try functionWillThrowError() } catch { // deal with error }
do-catch 機制簡單易懂。很多編程語言也使用類似的機制進行異常處理,但是在 Swift 中有一個比較重要的特性。
catch 和 switch 一樣具有 Pattern Matching 的能力。所以,使用 catch 你可以對異常的解析進行更為高級的處理
do { try functionWillThrowError() } catch MyError.NotExist { // deal with not exist } catch MyError.OutOfRange { // deal with not exist }
這里值得提一下在 Swift 2.0中一個跟異常處理沒有關系的改進
Swift 2.0 中沒有了 do-while循環,取而代之的是 repeat-while。蘋果說這個改動是為了增強代碼的可讀性。但是我更覺得是為了讓我們更舒服的使用 do-catch
不處理異常
如果我不想處理異常怎么辦,或者說,我非常確定某個方法或者函數雖然聲明會拋出異常,但是我自己知道我在使用時候是絕對不會拋出任何異常的。這種情況下 我們可以使用 try!
try! functionThrowErrorNil()
當然,如果你使用 try!,而你的方法或者函數拋出了異常,那么你會得到一個運行中異常 (runtime error) 所以我們開發者需要慎用哦。
Defer
文章結束前我們再討論下 defer
在你的代碼塊就要結束前。如果你使用了 defer。 在其之中的代碼就會運行。等于說,給了你最后的機會來進行一些處理。如果你熟悉 BDD 或者 TDD, 那么你可以參考他們中的 aferAll 機制
func myFunction() throws { defer { // No matter what happened I need do something print("All done, clean up here") } guard let item = item else { // need throws the error out throw MyError.NotExist } guard item.count > maxNumber else { // need throws the error out throw MyError.OutOfRange } // do something with item // ... }
注意,如果你有多個defer 語句,他們在執行的順序會和棧一樣,最后一個進,第一個出。
總結
-
使用 ErrorType 的幫助建立你的異常類型
</li> -
使用 throws 來聲明異常,用 throw 來拋出異常
</li> -
使用 do-catch 機制來獲取和處理異常
</li> </ul>
-