標籤:wwdc guard item params str tps ring pre param
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 endfunc 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 語句
- 只有在 guard 審查的條件成立,guard 之後的代碼才會運行 (像守衛一樣,條件不符就不讓過去)。
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 的協助建立你的異常類型
- 使用 throws 來聲明異常,用 throw 來拋出異常
- 使用 do-catch 機制來擷取和處理異常
Swift 2.0 異常處理