譯文:在 Swift 2 beta 6中使用 try? 拋出可選異常

title: "在 Swift 2 beta 6中使用 try? 拋出可選異常"
date: 2015-09-11
tags: [Swift]
categories: [Benedikt Terhechte]
permalink: optional-throw-swift


原文鏈接=http://appventure.me/2015/08/25/optional-throw-swift/
作者=Benedikt Terhechte 原文日期=2015/08/25
譯者=lfb_CD (已授權(quán))
校對=小鍋
定稿=Shanks

Swift2.0 b6 新增了一個(gè)關(guān)鍵字 try?,這為我們處理異常又增加一個(gè)新的途徑。這篇簡短的文章闡述了這個(gè)關(guān)鍵字的基礎(chǔ)知識,同時(shí)說明為何這個(gè)新關(guān)鍵字很酷。

在 Swift1.x 中,我們只能通過可選數(shù)據(jù)類型和 NSError 來處理異常。我們可以在其他編程語言中看到 Either/Result這樣的形式,于是很多人將這種形式移植到 Swift 當(dāng)中:

let success = Result<String, NSError>.Success("success")

在 Swift2.0 中, 蘋果引進(jìn)了 try/catch 的異常處理方式。在底層實(shí)現(xiàn)中,Swift 并沒有像其他編程語言(比如 Objective-C 或者 Java) 一樣使用代價(jià)昂貴的堆棧處理。相反地,它們返回了類似 Either 或者 Result 的東西 。從語法上隱藏了這些東西,就是為了使異常處理使用起來更加簡單1。

Swift 2 b5 或之前版本

然而,隨著代碼中使用 do/try/catch 的增多,你會發(fā)現(xiàn)代碼嵌套得越來越混亂,因?yàn)?do 與處理可選值(optionals)的語句看起來不兼容。這兒有一段丑陋的代碼,注意觀察我們是怎么用 let do let 嵌入到 if let 中的2。

import Foundation
// get the currently logged in user
func loggedInUser() -> Int? { return 0 }
// get his name
func getUserName (userId: Int) throws -> String { return "Claus" }
// create a new image post with this username. Returns the post data
func imagePostForUserName(name: String, imageURL: NSURL?) -> NSData? { return NSData() }
// post the data to a server
func postImage(data: NSData) throws -> Bool { return true }

if let uid = loggedInUser() {
    do {
    let username = try getUserName(uid)
    if let data = imagePostForUserName(username, imageURL: nil) {
        do {
        let success = try postImage(data)
        if success {
            print ("Submitted")
        }  
        } catch {
        // more error handling
        }
    }
    } catch {
    // todo: error handling
    }
}

很難對這段代碼進(jìn)行簡化的一個(gè)原因是, do 會打破我們使用多重 guardlet 的連續(xù)性3

Swift 2 b6

在beta6中,我們有了一個(gè)新的關(guān)鍵字 try? ,它在代碼執(zhí)行失敗時(shí)會拋出錯(cuò)誤并返回可選值 None,而在執(zhí)行成功的情況下,會直接返回可選值 Some。
以下直接引用官方的更新日志:

Swift 新添加了一個(gè)關(guān)鍵字try?。try?會試圖執(zhí)行一個(gè)可能會拋出異常的操作。如果操作執(zhí)行成功,執(zhí)行的結(jié)果就會包裹在可選值(optional)里;如果操作執(zhí)行失敗(比如某個(gè)錯(cuò)誤被拋出了),那么執(zhí)行的結(jié)果就是 nil,而且 error 變量會被丟棄。try? 在和 if letguard一起使用時(shí)的效果特別明顯。

這使得從一個(gè)潛在可能拋出錯(cuò)誤的操作中獲取到一個(gè)以可選形式表示的值成為可能。如果我們把這個(gè)應(yīng)用到上面的代碼,我們可以把它簡化不少:

if let uid = loggedInUser(),
   username = try? getUserName(uid),
   data = imagePostForUserName(username, imageURL: nil),
   success = try? postImage(data)
   where success == true {
      print ("Submitted")
}

當(dāng)然,這是一個(gè)有點(diǎn)做作的例子,專門為解釋 try? 而設(shè)計(jì)。但是,這絕對是可以縮減不少代碼的。當(dāng)然,我們也可能會丟失很多有用的錯(cuò)誤信息,而這些信息原本是可以用 catch 來獲取到的。

選擇哪一個(gè)?

try? 可以幫助你不用深入挖掘便寫出簡潔的代碼。使用 try? 只會返回一個(gè)可選值,不會含有更多的造成特定的錯(cuò)誤或者異常原因的信息。好處當(dāng)然就是可以和大量 Swift 的語法進(jìn)行完美的組合,比如, map, flatmap, switch, guard, if let, for case,以及其他。

非可選的 try 非常適合獨(dú)立的任務(wù), 這些任務(wù)不需要獲取之前或者之后可能存在的可選結(jié)果。

而上面提到的 Result 數(shù)據(jù)類型,則兩方面的信息都可以提供,不管是被請求的值或是可能的錯(cuò)誤。你可以繼續(xù)使用 Result,它也提供了對拋出的數(shù)據(jù)包裝和其他更多的支持,然而,你需要記住這似乎并不是 Swift 打算發(fā)展的方向4。否則,我們就應(yīng)該在 Swift 2 中看到完整的 Result 或者 Either 實(shí)現(xiàn)了。

try? 關(guān)鍵字的引進(jìn)使我感到十分高興,因?yàn)檫@將使得很多代碼段的編寫更加容易,特別是在與 Cocoa API 交互時(shí)。

  1. 就像 Swift 中通過?語句聲明的可選數(shù)據(jù)類型一樣try?也封裝了很多和可選相關(guān)的操作
  2. 也有不用try?的方法來改進(jìn)這里的代碼,但這段代碼是一個(gè)很好的例子
  3. 值得一提的是,我這里使用的是原生的 NSRegularExpression 而非第三方庫
  4. 你也需要在你的項(xiàng)目中添加相關(guān)的附加依賴項(xiàng)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容