Swift: 错误忽略 try 语句

Swift: Error ignores try statement

在我的代码中,我使用 SWXMLHash 库反序列化了一些 XML。它的 .value() 方法在其声明中有 throws 关键字,任何自定义反序列化函数也是如此。

我有下面一行代码:

let myValue : UInt8 = try? xml["Root"]["ValueNode"].value()

由于库不包含 UInt8 的反序列化器,我定义了自己的反序列化器:

extension UInt8: XMLElementDeserializable {
    public static func deserialize(_ element: XMLElement) throws -> UInt8 {
        return UInt8(element.text)!
    }
}

这在节点有值时有效。但是,当节点不存在或为 nil 时,会在以下行发生错误:

return UInt8(element.text)!  // Fatal error: Unexpectedly found nil while unwrapping an Optional value

这显然是应该发生的。我不明白的是为什么这个错误没有被我的 try? 语句捕获并返回 nil 而不是抛出那个错误。

有人能帮忙吗?

return UInt8(element.text)!

这一行没有try。因此,这里不会抛出任何错误。如果 UInt8 不能转换给定的字符串,它只是 returns nil。然后,当然,您的 !nil 变成了崩溃。

相反,做这样的事情:

guard let retVal = UInt8(element.text) else { throw SomeError }
return retVal

总的来说:如果有一种方法可以使用 ! 来做某事,而另一种方法可以不使用 ! 来做同样的事情,那就选择第二种,除非你真的有很好的理由。

并非所有错误都可以在Swift中捕获。如果您使用 throws 关键字标记函数,则表示该函数可能会抛出 可恢复 错误。但是,您的自定义实现实际上不会引发任何错误。只有用 throws 关键字标记的函数抛出的错误和使用代码 throw Error 抛出的错误才能被 do-catch 块捕获。

try? 是一种将可抛出函数的 return 值转换为可选值的方法。如果函数会抛出错误,try? 之后的值将是 nil,否则它将是一个可选值。

当你使用 ! 时,你明确地告诉编译器你知道你在做什么,如果你使用 ! 的操作失败,你的应用程序不应该优雅地失败.

您需要更改 deserialize 方法以优雅地处理可选的解包或抛出错误。

extension UInt8: XMLElementDeserializable {
    public static func deserialize(_ element: XMLElement) throws -> UInt8 {
        if let val = UInt8(element.text) {
            return val
        } else {
            throw NSError(domain: "Couldn't deserialize value to UInt8", code: 1)
        }
    }
}