0

在我的代码中,我使用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而不是抛出那个错误。

任何人都可以帮忙吗?

4

2 回答 2

1
return UInt8(element.text)!

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

取而代之的是,请执行以下操作:

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

一般来说:当有一种方法可以使用 做某事!,而另一种方法可以不使用 做同样的事情时!,除非你有充分的理由,否则请选择第二种方法。

于 2017-12-11T23:12:21.197 回答
1

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

try?是一种将可抛出函数的返回值转换为可选项的方法。如果函数会抛出错误,则后面的值为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)
        }
    }
}
于 2017-12-11T23:15:25.760 回答