1 - 这个代码块本身是否正确,或者将它包含在 do-catch 块中是否会更好?
答:这个代码是正确的。如果您的sampleJSON.json
文件在您的包中并且您的 JSON 文件中的数据格式正确并且JSONSerialization
成功解析所提供的数据,它将起作用。
2 - 我问是因为我看到使用 URLSession 从 Web 提取数据时的场景,开发人员在 do-catch 块内执行 JSONSerialization。是否有理由在使用 URLSession 时这样做,而不是在简单地从文件中提取 JSON 数据时这样做?这样的事情的最佳做法是什么?
A: do-catch 语句在使用来自 Web 的数据(在这种情况下为 JSON)时更常见,因为 API 可能因任何原因而中断(必须显示的数据的错误规范、Web 应用程序本身的错误等) ) 如果发生这种情况,我们不希望我们的应用程序崩溃。
我说 CRASH 是因为您使用了!
不会将错误传播到应用程序的上层,它会尝试强制操作,如果失败会使应用程序崩溃。
在这一点上,您可能已经意识到,在使用包中的数据时看不到 do-catch 语句的原因是应用程序开发人员自己提供了 JSON,所以我假设您确定文件的内容,但我' 仍然会使用 do-catch 语句,因为可能会出现问题并且不希望我的应用程序由于这样的愚蠢事情而崩溃。
TL;博士
我建议始终将错误传播与 throws/rethrows 一起使用,甚至?
可以测试 nil 结果。
我在这里写了一篇小文章,其中包含一些技巧以及它在 Swift 2.1 中的工作原理,在 Swift 3.1 中没有太大变化,因此您可以使用它来研究 do-catch 语句。
我会像这样重写您提供的代码:
警告:未经测试的代码
enum JSONFromFileError: Error {
case fileNotInBundle(String)
case deserializationError
case getDataError(URL)
}
func json(from file: String) throws -> Any {
// Fetch URL in Bundle
guard let url = Bundle.main.url(forResource: file, withExtension: "json") else {
throw JSONFromFileError.fileNotInBundle(file)
}
// Load Data from url
guard let data = try? Data(contentsOf: url) else {
throw JSONFromFileError.getDataError(url)
}
// Deserialize JSON
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
throw JSONFromFileError.deserializationError
}
return json
}
do {
let myJsonObject = try json(from: "sampleJSON")
print(myJsonObject)
} catch let error {
print(error)
}