我正在尝试使用包含json数据的文本文件中的数据。从各种来源,我能够成功地从文件中读取数据数组。但是,当我尝试在另一个do,try,catch块中使用函数之外的代码时,它会抱怨“变量xxx在初始化之前使用”
看看这里发布的答案,说要在do,try,catch块之外创建变量,但它只是移动了错误。
快速5(5.7.1)
CLI学习应用程序
单位. json
这是包含元素数组的示例JSON文件。
{
"units": [
{
"name":"cartman",
},
{
"name":"kyle",
}
]
}
文件IO.swift
这是执行fileIO的代码
import Foundation
// src https://stackoverflow.com/a/36827996/1008596
struct UnitData: Decodable {
var name: String = "none"
}
struct UnitsData: Decodable {
var units: [UnitData]
}
enum JFDFileError: Error {
case FileNotFound
case JSONDecodeFailed
}
// src https://www.swiftbysundell.com/articles/working-with-files-and-folders-in-swift/
func my_simple_file_read(path: String) throws -> UnitsData {
let file_name = (path as NSString).expandingTildeInPath
let url = URL(fileURLWithPath: file_name)
// Read the file
var data: Data
do {
data = try Data(contentsOf: url)
} catch {
throw JFDFileError.FileNotFound
}
var unitsData: UnitsData
do {
let decoder = JSONDecoder()
unitsData = try decoder.decode(UnitsData.self, from: data)
// these prints work
// prints entire json file
print("entire json file \(unitsData)")
// prints specific element of json array
print("this works 0 is \(unitsData.units[1].name)")
} catch {
throw JFDFileError.JSONDecodeFailed
}
// this print works
print("this works here \(unitsData.units[1].name)")
return unitsData
}
主.快速
这是主代码的一个摘录。它和函数的形式一样,但是函数调用的返回失败了。为什么?
// Read units from json file
var unitsData: UnitsData
do {
unitsData = try my_simple_file_read(path: "~/somepath/units.json")
// this works
print("works1 is \(unitsData.units[1].name)")
} catch {
print("an error occured")
}
// error: Variable 'unitsData' used before being initialized
print("does not work \(unitsData.units[1].name)")
3条答案
按热度按时间h5qlskok1#
关于
Main.swift
中的编译时错误:变量“unitsData”在初始化前使用
这是因为你有一个执行路径(
try my_simple_file_read
可能会抛出错误),其中unitsData
变量没有设置。所有的执行路径必须设置变量,否则编译器将生成一个错误,就像你在这里看到的。在
do
-catch
语句之后避免引用unitsData
(即,将所有unitsData
引用 * 放入 *do
块),或者在捕获到错误时退出,或者使unitsData
成为可选项并将其设置为catch
块中的nil
。函数实现的不同之处在于,如果捕捉到错误(在
catch
语句中是throw
,它会立即退出),并且没有到达函数中的最后一条print
语句,则会有一个“早期退出”,因此在变量初始化之前没有使用它。这与
Main.swift
示例形成对比,在catch
示例中,catch
语句只打印一条消息并继续执行,到达一个从未设置的unitsData
引用。编译器检测到这种误用并生成编译时错误。snvhrwxg2#
首先,John Sundell是一位严肃而可敬的Swift开发人员,他绝不会建议使用
my_simple_file_read(
这样的snake_case函数名,也不会通过打印无意义的字符串文字来丢弃错误。基本上,声明一个没有默认值的变量只有在保证变量在某个地方被初始化的情况下才有意义。
编译器会抛出一个错误,因为您没有在
catch
块中赋值。但是在您的情况下,在
do
范围内声明并初始化变量常量无论如何,如果函数
throws
是一个更好的实现框架引发的错误比自定义错误更严重。
vql8enpb3#
我今天学到了一些东西:
话虽如此,是解决方案,它演示了更好的方法来编写初始函数和原始函数,以显示为什么它的工作方式之一,而不是其他。即工作在原始代码与抛出,但不打印。
文件.swift
主.快速