快速强制解包异常未传播

问题描述 投票:0回答:3

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

来自文档:

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

重现:

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

还有

try foo(nil);

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

这是设计使然吗?

ios swift swift2
3个回答
20
投票

来自文档

错误处理

错误处理是响应并恢复的过程 程序中的错误情况。 Swift 提供一流的支持 用于投掷、接住、传播和操纵可恢复的 运行时出错。

...

表示和抛出错误

在 Swift 中,错误由符合以下条件的类型值表示

ErrorType
协议。这个空协议表明一个类型可以 用于错误处理。

(注意:

ErrorType
在Swift 3中已重命名为
Error

因此,使用

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

请注意,有关错误处理的 Swift 文档甚至没有使用 “例外”一词,唯一的例外(!)在(强调我的):

注意

Swift 中的错误处理类似于其他语言中的异常处理 语言,使用 try、catch 和 throw 关键字。不像 许多语言(包括 Objective-C)中的异常处理错误 Swift 中的处理不涉及展开调用堆栈,这是一个过程 这在计算上可能是昂贵的。因此,性能 throw 语句的特性与 退货声明。

展开

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

您必须使用众所周知的技术,例如 可选绑定、可选链接、检查

nil
等。


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

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


0
投票

强制展开的实现完全按照文档描述!但您可能正在寻找这样的东西:

try myOptional.unwrapped() // Throws an error if it is `nil`

这个 trowing

unwrapped
功能可以简单地实现如下:

extension Optional {
    enum Error: Swift.Error {
        case unexpectedNil
    }

    func unwrapped() throws -> Wrapped {
        if let self { return self }
        else { throw Error.unexpectedNil }
    }
}

所以现在你可以

catch Optional.Error.unexpectedNil

© www.soinside.com 2019 - 2024. All rights reserved.