ios 如何在SwiftUI中表示JSON文件?

mgdq6dx1  于 2022-12-27  发布在  iOS
关注(0)|答案(1)|浏览(144)

我是一个相当初学者,并试图让OpenWeather API JSON显示在我的挑战项目。
我设法模拟了一下

struct WeatherRespose: Codable {
    var weather: [Weather]
    var name: String
}

&

import Foundation

struct Weather: Hashable, Codable {
    var main: String
    var description: String
}

除了在ContentView中获取数据之外。然而,当我试图呈现它时:
@State var weatherForcast = Weather()@State var weatherForcast = WeatherResponse()我得到这个错误:调用中缺少参数“from "的自变量,请插入”from:〈#解码器#〉'
唯一对我有用的是将数据表示在数组中:
@State var weatherForcast = [Weather]()
知道我错过了什么吗?太谢谢你了!兰

v09wglhw

v09wglhw1#

我做了一个非常简单的例子来说明如何做到这一点。这里有几个额外的文件,所以更容易理解它是如何工作的细节:
1.创建名为NetworkService的附加文件,它将获取天气数据:

import Foundation

final class NetworkService{

    private let url = "https://example.com"
    
    func performWeatherRequest(completion: @escaping (Result<WeatherResponse, Error>) -> Void){
            URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
                guard let data = data, error == nil else {
                    completion(.failure(WeatherError.failedToDownload))
                    return
                }
                                
                let weatherResponse: WeatherResponse = try! JSONDecoder().decode(WeatherResponse.self, from: data)
            
                completion(.success(weatherResponse))
                
            }.resume()
    }
    public enum WeatherError: Error {
            case failedToDownload
    }
}

1.创建简单的ViewModel,它将从我们的NetworkService中检索数据,并准备在ContentView中显示它

import Foundation
import SwiftUI

extension ContentView {
    @MainActor class ContentViewVM: ObservableObject {
        private var networkService = NetworkService()
        
        @Published var currentWeatherMain: String?
        @Published var currentWeatherDescription: String?
        
        func fetchWeather(){
            networkService.performWeatherRequest { [weak self] result in
                DispatchQueue.main.async {
                    switch result {
                    case .success(let weatherResponse):
                        self?.currentWeatherMain = weatherResponse.weather[0].main
                        self?.currentWeatherDescription = weatherResponse.weather[0].description
                    case .failure(_):
                        print("oops, error occurred")
                    }
                }
            }
        }
    }
}

1.将我们的ContentViewVM添加到我们的ContentView

import SwiftUI

struct ContentView: View {
    @StateObject var viewModel = ContentViewVM()
    
    var body: some View {
        VStack {
            Text("The main is: \(viewModel.currentWeatherMain ?? "")")
            Text("The description is: \(viewModel.currentWeatherDescription ?? "")")
        }
        
        .onAppear{
            viewModel.fetchWeather()
        }
    }
}

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

希望有帮助。

相关问题