2016-01-06 21 views
14

我已經遇到了這種愚蠢的行爲,在強制解包可選不會傳播的swift中。迅速的力量解開異常沒有傳播

從文檔:

嘗試使用!訪問不存在的可選值會觸發運行時錯誤。在使用之前,務必確保可選項包含非零值!強迫 - 解開其價值。

重現:

func foo(bar:String?) throws{ 
    print(bar!); 
} 

而且

try foo(nil); 

這似乎不符合邏輯,或者我一致,我無法找到任何關於這一問題的文件。

這是設計嗎?

+2

我不確定用'throw'(這是什麼原因導致錯誤在這個函數內傳播)拋出一個錯誤與當你強制解開一個'nil'時發生的錯誤是一樣的。我想我在某處讀到它是作爲'assert()'實現的。 –

+0

這可以解釋它,但那太可怕了。也許有爭論,但支持異常的語言似乎不一致。 – Greg

+7

@格雷格:尼古拉斯是對的。請注意,try/catch處理Swift *錯誤*(符合'ErrorType'的值被拋出)。這與運行時錯誤或異常完全無關。 (文檔甚至沒有提及與throw/try/catch有關的「異常」這個詞,只有「錯誤處理」。) –

回答

10

documentation

錯誤處理

錯誤處理響應,並在你的程序 錯誤條件中恢復的過程。 Swift提供了一流的支持 用於在運行時拋出,捕獲,傳播和操作可恢復的錯誤 。

...

代表和引發錯誤

在夫特,錯誤是由的符合 的ErrorType協議類型值表示。這個空協議表明一個類型可以用於錯誤處理。

(注:ErrorType已更名爲Error斯威夫特卡倫特3)

因此,與try/catch你處理斯威夫特錯誤這是throw N(那符合ErrorType協議類型的值)。 這與運行時錯誤和運行時異常 (並且與Foundation庫中的NSException無關)完全無關。

注意,在錯誤處理雨燕文檔甚至不使用 詞「異常」,唯一的例外中(重點煤礦)(!):

注意

錯誤處理在Swift 類似異常處理在其他 語言,使用try,catch和throw關鍵字。與 許多語言中的異常處理(包括Objective-C錯誤 )在Swift中的處理不涉及展開調用堆棧,這是一個過程 ,可能在計算上很昂貴。因此,throw語句的性能與 return語句的性能相當。

自選的解纏它們nilthrow一個 夫特誤差(其可以被傳播),並不能與 try處理。

必須使用衆所周知的技術,如 可選的結合,可選鏈接,覈對nil

+0

我從來沒有嘗試過使用嘗試去解開,我只談論它們的傳播。但你回答得很好。 我碰到的一個用例是使用SwiftyJSON和解析json。我有一個實體,它包含一個只需在json響應中拋出(傳播)不存在的字段的子實體。 我現在使用可選初始值設定項來實現相同的操作,但是現在還有3行代碼:P – Greg

+0

@Greg:好的,任何拋出的錯誤都必須在某處捕捉。但我已經改變了措辭以更好地匹配你的問題。 –

5

這種「自我解釋」的例子可以幫助你看到拋出一個運行時異常和投擲的區別符合ErrorType協議的錯誤E.

struct E: ErrorType{} 
func foo(bar:String?) throws { 
    if let error = bar where error == "error" { 
      throw E() 
    } 
    print(bar, "is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil)") 
    // here is everything OK 
    let bar = bar! 
    // but here it crash!! 
    _ = bar.characters 
} 

do { 
    try foo("error") 
    // next line is not accessible here ... 
    try foo(nil) 
} catch { 
    print("\"error\" as parameter of foo() throws an ERROR!") 
} 
do { 
    try foo(nil) // fatal error: unexpectedly found nil while unwrapping an Optional value 
} catch { 

} 

它打印

"error" as parameter of foo() throws an ERROR! 
nil is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil) 
fatal error: unexpectedly found nil while unwrapping an Optional value 

拋出一個運行時異常是在你的代碼的致命錯誤。