快速的力 - 展开异常没有传播

时间:2016-01-06 08:54:21

标签: ios swift swift2

我在swift中遇到了这种愚蠢的行为,其中强制解包一个可选项不会传播。

来自文档:

  

尝试使用!访问不存在的可选值会触发运行时错误。在使用之前,请务必确保可选项包含非零值!强行解开它的价值。

重现:

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

try foo(nil);

这对我来说似乎不合逻辑或一致,我找不到有关此主题的任何文档。

这是设计吗?

2 个答案:

答案 0 :(得分:12)

来自documentation

  

错误处理

     

错误处理是响应和恢复的过程   程序中的错误条件。 Swift提供一流的支持   用于投掷,捕捉,传播和操纵可恢复的   运行时的错误。

     

...

     

代表和抛出错误

     

在Swift中,错误由符合的类型的值表示   ErrorType协议。这个空协议表明类型可以   用于错误处理。

(注意:ErrorType已在Swift 3中重命名为Error

因此,使用try/catch处理 Swift错误(符合ErrorType协议的类型的值)throw n。 这与运行时错误和运行时异常完全无关 (也与基金会图书馆的NSException无关。)

请注意,有关错误处理的Swift文档甚至不使用 word" exception",唯一例外(!)in(强调我的):

  

请注意

     

Swift中的错误处理在其他方面类似于异常处理   语言,使用try,catch和throw关键字。不像   许多语言的异常处理 - 包括Objective-C-error   Swift中的处理不涉及展开调用堆栈,这是一个过程   这可能是计算上昂贵的。就这样,表现   抛出语句的特征与a的特征相当   退货声明。

nil选项的展开不会throw a Swift错误(可以传播)并且无法处理 try

你必须使用像这样众所周知的技术 可选绑定,可选链接,检查nil等。

答案 1 :(得分: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

引发运行时异常是代码中的致命错误。