【问题标题】:swift force-unwrapping exception not propagated快速强制展开异常未传播
【发布时间】:2016-04-10 07:11:43
【问题描述】:

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

来自文档:

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

复制:

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

try foo(nil);

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

这是设计的吗?

【问题讨论】:

  • 我不确定使用throw 引发错误(这会导致错误从此类函数中传播)与强制解开@987654324 时发生的事情相同@。我想我在某处读到它被实现为assert()
  • 这可以解释,但那太可怕了。也许有一个论据,但在支持异常的语言中,它似乎不一致。
  • @Greg:尼古拉斯是对的。请注意,try/catch 处理 Swift errors(抛出符合 ErrorType 的值)。这与运行时错误或异常完全无关。 (文档甚至没有提到与 throw/try/catch 相关的“异常”一词,只提到“错误处理”。)
  • 我猜很容易将 swift 错误与异常混淆。大多数其他编程语言使用类似的关键字(try/catch)来处理异常处理。

标签: ios swift swift2


【解决方案1】:

来自documentation

错误处理

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

...

表示和抛出错误

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

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

所以使用try/catch,您可以处理thrown 的Swift 错误(符合ErrorType 协议的类型的值)。 这与运行时错误和运行时异常完全无关 (也与 Foundation 库中的 NSException 无关)。

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

注意

Swift 中的错误处理类似于其他中的异常处理 语言,使用 try、catch 和 throw 关键字。不像 许多语言的异常处理——包括Objective-C——错误 在 Swift 中处理不涉及展开调用堆栈,一个过程 这在计算上可能很昂贵。如此一来,表现 throw 语句的特征与 返回语句。

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

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

【讨论】:

  • 我从未尝试过使用 try 捕捉展开,我只谈论它们的传播。但你回答得很好。我遇到的一个用例是使用 SwiftyJSON 和解析 json。我有一个实体,它包含一个子实体,它只会在 json 响应中抛出(传播)不存在的字段。我现在使用可选的初始值设定项来实现相同的目标,但现在多了 3 行代码:P
  • @Greg:好吧,任何抛出的错误都必须在某个地方捕获。但我已经更改了措辞以更好地匹配您的问题。
【解决方案2】:

这个“自我解释”示例可以帮助您了解引发运行时异常和抛出符合 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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-17
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2016-06-24
    • 2015-12-25
    相关资源
    最近更新 更多