将@ObservableObject传递到SwiftUI内容视图中

问题描述 投票:0回答:1

[尝试通过API调用将@ObservedObject数据传递到SwiftUI内容视图。

使用API​​调用中的打印命令,我可以看到数据已提取并解码正常。

但是尝试将@Published数据传递到ContentView进行显示会产生错误:Instance member 'byCountry' cannot be used on type 'DataModel'(DataModel是数据的结构)。

这里的数据结构:


class DataModel: Decodable {
    let global : Global
    let byCountry: [ByCountry]
    let date: String

    enum CodingKeys: String, CodingKey {
        case global = "Global"
        case byCountry = "Countries"
        case date = "Date"
    }

    struct Global: Decodable {
        let globalNC: Int
        let globalTC: Int
        let globalND: Int
        let globalTD: Int
        let globalNR: Int
        let globalTR: Int

        enum CodingKeys: String, CodingKey {
            case globalNC = "NewConfirmed"
            case globalTC = "TotalConfirmed"
            case globalND = "NewDeaths"
            case globalTD = "TotalDeaths"
            case globalNR = "NewRecovered"
            case globalTR = "TotalRecovered"
        }
    }

    struct ByCountry: Decodable {
        let cntry: String
        let ccode: String
        let slug: String
        let cntryNC: Int
        let cntryTC: Int
        let cntryND: Int
        let cntryTD: Int
        let cntryNR: Int
        let cntryTR: Int
        let date: String

        enum CodingKeys: String, CodingKey {
            case cntry = "Country"
            case ccode = "CountryCode"
            case slug = "Slug"
            case cntryNC = "NewConfirmed"
            case cntryTC = "TotalConfirmed"
            case cntryND = "NewDeaths"
            case cntryTD = "TotalDeaths"
            case cntryNR = "NewRecovered"
            case cntryTR = "TotalRecovered"
            case date = "Date"
        }
    }
}

这里是API调用:

class APICall : ObservableObject, Identifiable {

    @Published var dataPull = DataModel.self

    init() {
        let urlCall = URL(string: "https://api.covid19api.com/summary")
        guard urlCall != nil else {
            print("Error reaching API")
            return
        }
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlCall!) { (data, response, error) in
            if error == nil && data != nil {
                let decoder = JSONDecoder()
                do {
                    let dataPull = try decoder.decode(DataModel.self, from: data!)
                    print(dataPull.global.globalNC)
                }
                catch {
                    print("Server busy, try again in 5 min.")
                }
                DispatchQueue.main.async {
                    self.dataPull = self.dataPull
                }
            }
        }
        dataTask.resume()
    }
}

在APICall中打印提取和解码的数据有效并且正确。

这里是ContentView代码:

import SwiftUI

struct ContentView: View {

    @ObservedObject var apiCall = APICall()

    var body: some View {

        Text($apiCall.dataPull.byCountry[35].cntry)
    }

    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }

}

简单文本显示Text($apiCall.dataPull.byCountry[35].cntry)会同时提示Initializer 'init(_:)' requires that 'Binding<String>' conform to 'StringProtocol'错误,和Instance member 'byCountry' cannot be used on type 'DataModel'错误。

由于我是初学者,无法找到错误问题的答案,并且想象这是直接失败。

其他问题...我使用了一个示例,如图所示在APICall中实现了“ init(){..”。但是我还打算在ContentView中添加一个按钮,以在按钮操作时执行APICall来刷新数据。当使用“ init()”代替函数调用时如何执行?

感谢任何帮助。谢谢。

swiftui init
1个回答
0
投票

两件事...

class APICall : ObservableObject, Identifiable {

    @Published var dataPull: DataModel? = nil   // here !!

struct ContentView: View {

    @ObservedObject var apiCall = APICall()

    var body: some View {
        if apiCall.dataPull != nil {   // only when there is data
            // !! pay attention - you hardcoded 35th element, but it
            // !! might be absent in response - then crash
            Text(apiCall.dataPull!.byCountry[35].cntry) // here !!
        } else {
            Text("Loading...")
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.