我有两段代码来解码 json 数据(本地和远程)。两者都有效。我还可以可视化本地数据,但不能可视化远程数据。它们完全相同(只是 json 文件和 imageUrl 的位置不同)。在我的 TestView.swift 代码(用于这两种情况)中,我给出了两条指出我的问题的注释。
我的问题:如何为远程案例定义 testData:[Test],而本地案例已明确定义该测试数据?
缺少什么?请帮忙。我是 Xcode 和 SwiftUI 的新手,因此我们将不胜感激任何帮助。
附注基本上,我试图在两个 Swift 教程(在 YouTube 上)的基础上进行构建,即从头到尾使用 SwiftUI 构建复杂的 UI、使用 BindableObject 的 SwiftUI 获取 JSON 和图像数据。
//Data.swift
import SwiftUI
import Combine
//1.) 第一段代码解码本地 json 数据并正确可视化它
let testData:[Test] = load("test.json")
func load<T:Decodable>(_ filename:String, as type:T.Type = T.self) -> T {
let data:Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
//2.) 第二段代码解码远程 json 数据,但不将其可视化
class testDatas: ObservableObject {
@Published var tests:[Test] = [Test]()
func getAllTests() {
let file = URLRequest(url: URL(string: "https://myurl/test.json")!)
let task = URLSession.shared.dataTask(with: file) { (data, _, error) in
guard error == nil else { return }
do {
let tests = try JSONDecoder().decode([Test].self, from: data!)
DispatchQueue.main.async {
self.tests = tests
print(tests)
}
} catch {
print("Failed To decode: ", error)
}
}
task.resume()
}
init() {
getAllTests()
}
init(tests: [Test]) {
self.tests = tests
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
//TestView.swift(用于两种解码情况)
import SwiftUI
// testData needed here only for the remote case, but this might be wrong and the problem?
let testData:[Test] = [Test]()
struct TestView: View {
// testDatas needed here only for the remote case to decode json data)
@ObservedObject var fixer: testDatas = testDatas()
@EnvironmentObject var loader: ImageLoader
var categories:[String:[Test]] {
.init(
grouping: testData,
by: {$0.category.rawValue}
)
}
var body: some View {
NavigationView{
List (categories.keys.sorted(), id: \String.self) {key in TestRow(categoryName: "\(key).environmentObject(ImageLoader(with: key.imageUrl)) Tests".uppercased(), tests: self.categories[key]!)
.frame(height: 320)
.padding(.top)
.padding(.bottom)
}
.navigationBarTitle(Text("TEST"))
}
}
}
class ImageLoader:ObservableObject
{
@Published var data:Data = Data()
func getImage(imageURL:String) {
guard let test = URL(string: imageURL) else { return }
URLSession.shared.dataTask(with: test) { (data, response, error) in
DispatchQueue.main.async {
if let data = data {
self.data = data
}
}
print(data as Any)
}.resume()
}
init(imageURL:String) {
getImage(imageURL: imageURL)
}
}
struct TestView_Previews: PreviewProvider {
@ObservedObject var imageLoader: ImageLoader
init(test:String)
{
imageLoader = ImageLoader(imageURL: test)
}
static var previews: some View {
TestView()
}
}
最佳答案
在@Josh Homann 对相关问题的帮助下,我可以解决我的问题。我所要做的就是将“分组:testData”替换为“分组:networkManager.tests”并使用“@ObservedObject var networkManager:NetworkManager = NetworkManager()”。这使得 testData 的定义变得多余。
关于swift - 尽管使用 SwiftUI 成功解码 json 数据,但没有图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58531681/