SwiftUI с JSON ObservedObject - PullRequest
       33

SwiftUI с JSON ObservedObject

0 голосов
/ 19 апреля 2020

В настоящее время я изучаю SwiftUI, и у меня возникают проблемы с получением кода для печати вызова из API

NetworkManager.swift

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()
        }
    }
}

Если я распечатаю все страны, я вижу каждый элемент

Но на моем главном экране при попытке печати (self.networkManager [5] .name) я получаю индекс из-за ошибки диапазона

ContentView.swift

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()
    }
}

Может кто-нибудь помочь указать, где я иду не так?

Ответы [ 2 ]

0 голосов
/ 19 апреля 2020

Вы пытаетесь получить доступ к .allCountries слишком рано, потому что .fetchAllCountries - это длинная (относительно) асинхронная операция.

Решение состоит в том, чтобы добавить явного наблюдателя в выбранные страны, как показано ниже

* 1006. *
0 голосов
/ 19 апреля 2020

проблема связана с асинхронным fetchAllCountries. Вам нужно подождать, пока оно не закончится, прежде чем пытаться использовать результаты. Попробуйте что-то вроде этого;

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)
            }
    }
}
}
...