首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用JSON ObservedObject的SwiftUI

使用JSON ObservedObject的SwiftUI
EN

Stack Overflow用户
提问于 2020-04-19 07:06:39
回答 2查看 483关注 0票数 0

我目前正在学习SwiftUI,并且在从API打印调用的代码中遇到了问题。

NetworkManager.swift

代码语言:javascript
复制
class NetworkManager: ObservableObject {

    @Published var allCountries = Countries()

    func fetchAllCountries() {
        if let url = URL(string: K.url) {
            print(url)
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { (data, response, error) in
                if error == nil {
                    let decoder = JSONDecoder()
                    if let countriesData = data {
                        do {
                            let countries = try decoder.decode(Countries.self, from: countriesData)
                            DispatchQueue.main.async {
                                self.allCountries = countries
                            }
                        } catch {
                            print(error)
                        }
                    }
                }
            }
            task.resume()
        }
    }
}

如果我打印allCountries,我可以看到每一项

但是在我的主视图上,当我尝试打印(self.networkManager5.name)时,我得到一个索引超出范围的错误

ContentView.swift

代码语言:javascript
复制
import SwiftUI

struct ContentView: View {

    @ObservedObject var networkManager = NetworkManager()

    var body: some View {
        Text("Hello, World!")
            .onAppear {
                self.networkManager.fetchAllCountries()
                print(self.networkManager.allCountries[5].name)
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

有人能帮我指出我哪里错了吗?

EN

回答 2

Stack Overflow用户

发布于 2020-04-19 07:23:26

问题出在异步fetchAllCountries上。在尝试使用结果之前,您需要等待它完成。试试这样的东西;

代码语言:javascript
复制
class NetworkManager: ObservableObject {

@Published var allCountries = Countries()

func fetchAllCountries(handler: @escaping () -> Void) {
    if let url = URL(string: K.url) {
        print(url)
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: url) { (data, response, error) in
            if error == nil {
                let decoder = JSONDecoder()
                if let countriesData = data {
                    do {
                        let countries = try decoder.decode(Countries.self, from: countriesData)
                        DispatchQueue.main.async {
                            self.allCountries = countries
                            return handler()
                        }
                    } catch {
                        print(error)
                    }
                }
            }
            handler()
        }
        task.resume()
    }
}
}

struct ContentView: View {

@ObservedObject var networkManager = NetworkManager()

var body: some View {
    Text("Hello, World!")
        .onAppear {
            self.networkManager.fetchAllCountries() {
                print(self.networkManager.allCountries[5].name)
            }
    }
}
}
票数 0
EN

Stack Overflow用户

发布于 2020-04-19 13:00:23

您试图过早地访问.allCountries,因为.fetchAllCountries是一个很长的(相对)异步操作。

解决方案是向获取国家添加显式观察者,如下所示

代码语言:javascript
复制
    var body: some View {
        Text("Hello, World!")
            .onAppear {
                self.networkManager.fetchAllCountries()
            }
            .onReceive(networkManager.$allCountries) { countries in
                 print(countries[5].name) // assuming Countries support subscript
            }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61297467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档