作者:Erica Sadun,原文鏈接强霎,原文日期:2015-08-27
譯者:CMB宣吱;校對:numbbbbb;定稿:千葉知風
假設你正在使用一個類型明未,當有錯誤時發(fā)生時你想要輸出異常發(fā)生時的上下文槽华。通常你會使用一些內(nèi)置的編譯器關(guān)鍵字:__FUNCTION__
, __LINE__
和 __FILE__
趟妥,這些關(guān)鍵詞提供了有關(guān)函數(shù)調(diào)用詳細的文本插值:
public struct Error: ErrorType {
let source: String; let reason: String
public init(_ reason: String, source: String = __FUNCTION__,
file: String = __FILE__, line: Int = __LINE__) {
self.reason = reason; self.source = "\(source):\(file):\(line)"
}
}
一行典型的 Error
輸出如下所示:
Error(source: "myFunction():<EXPR>:14", reason: "An important reason")
雖然這種結(jié)構(gòu)能夠讓你捕獲出現(xiàn)異常的函數(shù)猫态、文件和行號,但你無法捕捉?jīng)]有類型參數(shù)的原始父類型煮纵。為了捕獲該類型懂鸵,需要在 Error
結(jié)構(gòu)體構(gòu)造器中包含“原始類型”,并向構(gòu)造器中傳遞 self.dynamicType
參數(shù)行疏。
public struct Error: ErrorType {
let source: String; let reason: String
public init(_ reason: String, type: Any = "",
source: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
self.reason = reason; self.source = "\(source):\(file):\(line):\(type)"
}
}
我很不喜歡這種額外添加類型參數(shù)的方式匆光,它唯一的作用就是簡化錯誤生成。
public struct Parent {
func myFunction() throws {
throw Error("An important reason", type: self.dynamicType)}
}
do {try Parent().myFunction()} catch{print(error)}
// Error(source: "myFunction():<EXPR>:14:Parent", reason: "An important reason")
我更喜歡擴展 Contextualizable
來實現(xiàn)自動捕獲類型上下文酿联。注意终息,默認實現(xiàn)的協(xié)議方法中用到了 self.dynamicType
,它不能被用在方法簽名中(譯者注:也就是說不能當做函數(shù)參數(shù)或者返回值)贞让。
protocol Contextualizable {}
extension Contextualizable {
func currentContext(file : String = __FILE__, function : String = __FUNCTION__, line : Int = __LINE__) -> String {
return "\(file):\(function):\(line):\(self.dynamicType)"
}
}
結(jié)合上述兩種方法可以簡化整個過程輕松實現(xiàn)我們的目標周崭。共享 Error
類型之后就可以把變量改成常量,并且把上下文相關(guān)代碼從 Error
構(gòu)造器移動到遵循協(xié)議的類型中喳张,這樣就可以自動繼承 currentContext
方法续镇。
public struct Error: ErrorType {
let source: String; let reason: String
public init(_ source: String = __FILE__, _ reason: String) {
self.reason = reason; self.source = source
}
}
public struct Parent: Contextualizable {
func myFunction() throws {
throw Error(currentContext(), "An important reason")}
更新之后,錯誤輸出中會包含原始類型销部。
正如讀者 Kametrixom
所指出的摸航,你還可以擴展 Contextualizable
協(xié)議并創(chuàng)建你自己的錯誤。(他還寫了一個非常棒的錯誤類型舅桩,可以選擇是否添加上下文酱虎。)
本文的所有代碼可以在 這個 Gist 中找到(譯者注:Gist 已經(jīng)被墻,需要翻墻查看)擂涛。