首页 > 解决方案 > 尽管使用 SwiftUI 成功解码了 json 数据,但没有图像

问题描述

我有两段代码来解码 json 数据(本地和远程)。两者都有效。我还能够可视化我的本地数据,但不能可视化远程数据。它们完全相同(只是 json 文件和 imageUrl 的位置不同)。在用于这两种情况的 TestView.swift 代码中,我给出了两条指出我的问题的注释。

我的问题:我如何需要为远程案例定义 testData:[Test],这对于本地案例来说是很好的定义?

什么不见​​了?请帮忙。我是 Xcode 和 SwiftUI 的新手,因此我们将不胜感激。

PS 基本上我正在尝试构建两个 Swift 教程(在 YouTube 上),即从头到尾使用 SwiftUI 构建复杂的 UI,使用 BindableObject 获取 JSON 和图像数据的 SwiftUI。

// 数据.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()
    }
}

标签: swiftswiftui

解决方案


在@Josh Homann 在相关问题上的帮助下,我可以解决我的问题。我所要做的就是将“grouping: testData”替换为“grouping: networkManager.tests”并使用“@ObservedObject var networkManager: NetworkManager = NetworkManager()”。这使得 testData 的定义变得多余。


推荐阅读