【发布时间】:2021-01-08 23:07:54
【问题描述】:
假设我有一个包含这些数据的 JSON:
[
{ "id": "a",
"x": 1,
"y": 1 },
{ "id": "b",
"x": 7,
"y": 12 },
.
.
.
{etc.}
]
在 Swift 中,我可以将其加载到结构中:
struct jsonDataStruct: Codable, Identifiable {
let id: String
let x: Int
let y: Int
}
但是,例如,如果我想计算 x 和 y 之间的距离怎么办?通常,我编写了一个带有初始化器的结构,如下所示:
struct coordinates: Identifiable {
let id: String
let x: Int
let y: Int
let length: Int?
init(id: String, x: Int, y: Int) {
self.x = x
self.y = y
self.distance = sqrt(x * x + y * y)
// do other calculations or processing
}
}
当我创建一个对象时:
let dudeWheresMyCar = coordinates(id: "my car", x: 12, y: 18)
print("it's \(dudeWheresMyCar.distance) meters away")
在创建坐标对象时自动计算距离。
我将如何使用上面的 struct jsonDataStruct 做到这一点?我已经为它编写了一个初始化程序,但是当从 JSON 加载数据时它似乎没有被调用:
Bundle-Decodable.swift:
import Foundation
extension Bundle {
func decode(_ file: String) -> [jsonDataStruct] {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode([jsonDataStruct].self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
ContentView.Swift:
import SwiftUI
struct ContentView: View {
let testJsonData = Bundle.main.decode("testData.json")
var body: some View {
Text("\(testJsonData.count)")
.padding()
}
}
我可以在运行时根据需要简单地计算距离或任何其他值,但是预先计算它意味着它已经准备好使用,并且不必编写额外的代码。
我确信这个基本问题之前已经回答过,但作为一名业余编码员,我很可能会错过它,因为我可能不知道要查找什么或如何提出问题。
谢谢!
【问题讨论】:
-
首先,属性
distance(或length- 你都有)更好地表示为计算属性var distance: Double { sqrt(x * x + y * y) }- 这样你根本不需要解码它。或者,您需要编写自定义init(from: Decoder)并在那里计算distance。此外,强烈建议遵循大写类型名称的 Swift 约定:struct JsonDataStruct { }、struct Coordinates { } -
非常感谢您的建议!我还有很多东西要学