获取JSON数据并将其显示到列表中SwiftUI

3npbholx  于 2023-05-19  发布在  Swift
关注(0)|答案(2)|浏览(172)

我的屏幕上没有显示数据。我认为我的获取数据功能不能正常工作,但我可以将结果打印到控制台。我也认为这可能是模拟器的问题,但我在iPhone上测试了这个应用程序。我想我对天气模型(JSON)有问题。我在生成器里生成的。我从https://open-meteo.com/下载数据。我想导出当前天气和未来7天的最小值和最大值。我如何更改我的json,以便我的数据显示在应用程序中。谢谢你的帮助。

_________ ContentView

import SwiftUI
import Foundation

struct ContentView: View {
    //Since the response is an array of TaskEntry object
    @State var results = [WeatherModel]()

    var body: some View {
        // Here, i think i have problem.
        VStack{
            ForEach(results, id: \.id) { result in
                Text("\(result.currentWeather.temperature)")
            }
        }.onAppear(){
            WeatherService().getDate()
            print("Check point")
        }
    }
}

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


__________________ fetch  data 


class WeatherService : ObservableObject{
    let weatherService = WeatherService()
    let urlapi = "https://api.open-meteo.com/v1/forecast?latitude=52.40&longitude=13.07&daily=weathercode,temperature_2m_max,temperature_2m_min&current_weather=true&past_days=1&timezone=Europe%2FBerlin"
    
//    let url = "https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&current_weather=true"
    
    func getDate(){
        let url = urlapi
        URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in
            
            guard let data = data, error == nil else{
                print("Something went wrong")
                return
            }
            
            var result: WeatherModel
            do {
                result = try JSONDecoder().decode(WeatherModel.self, from: data)
                print(result)
            }
            catch {
                print("Convert Error: \(error.localizedDescription)")
                print(String(describing: error))
            }

        }).resume()
        
        
    }
}

__________________ Model Weather

import Foundation

struct WeatherModel: Decodable, Identifiable {
    var id = UUID()
    let currentWeather: CurrentWeather
    let daily: Daily

    enum CodingKeys: String, CodingKey {
        case currentWeather = "current_weather"
        case daily
    }
}

// MARK: - CurrentWeather
struct CurrentWeather: Decodable, Identifiable, Hashable {
    var id = UUID()
    let temperature: Double
    let isDay: Int
    let time: String

    enum CodingKeys: String, CodingKey {
        case temperature
        case isDay = "is_day"
        case time
    }
}

// MARK: - Daily
struct Daily: Decodable, Identifiable, Hashable {
    var id = UUID()
    let time: [String]
    let temperature2MMax, temperature2MMin: [Double]

    enum CodingKeys: String, CodingKey {
        case time
        case temperature2MMax = "temperature_2m_max"
        case temperature2MMin = "temperature_2m_min"
    }
}

我可以打印我的结果在终端,但我不能显示在屏幕上的应用程序。我想显示我当前的天气温度和下周的温度。

my output data:
WeatherModel(id: BF7EFC9E-9229-425B-AAE6-9D3131013FBF:
currentWeather: interTask.CurrentWeather(id: 57FE4881-3127-4A0A-A685-125AEC935676, temperature: 14.6, isDay: 1, time: "2023-05-17T15:00"), daily: interTask.Daily(id: EDE9C3AD-7415-48F8-AB3C-536CAF709204, time: ["2023-05-16", "2023-05-17", "2023-05-18", "2023-05-19", "2023-05-20", "2023-05-21", "2023-05-22", "2023-05-23"], temperature2MMax: [16.4, 15.0, 15.7, 18.3, 20.9, 26.0, 25.9, 26.5], temperature2MMin: [10.1, 6.3, 6.3, 7.8, 9.1, 14.2, 14.9, 14.5]))
2ul0zpep

2ul0zpep1#

通常你的服务是一个EnvironmentKey,下载将在.task中完成,例如。

struct ContentView: View {
    @Environment(\.weatherService) private var weatherService

    @State var results = [WeatherResult]()

    var body: some View {
        List {
            ForEach(results, id: \.id) { result in
                Text(result.currentWeather.temperature, format: .measurement(width: .wide))
            }
        }
        .task{
            results = await weatherService.fetchResults()
        }
    }
}
eagi6jfj

eagi6jfj2#

我把它修好了,现在可以显示当前的天气了。谢谢你的帮助。我添加了@Published属性,注意到了ObservableObject协议。
我的代码:
----ContentView

import SwiftUI
import Foundation

struct ContentView: View {
    //Since the response is an array of TaskEntry object
    @State var results = [WeatherModel]()

    var body: some View {
        
        VStack{
            VStack{
                ForEach(results, id: \.id) { result in
                    Text("\(result.currentWeather.temperature)")
                    Text("\(result.currentWeather.time)")
                    // how i can print min and max weather for next 7 days
                    HStack{
                        VStack{
                            Text("Max temp for next 7 days")
                            ForEach(1..<8) { index in
                            Text("\(result.daily.temperature2MMax[index])")
                            }
                        }
                        VStack{
                            Text("Min temp for next 7 days")
                            ForEach(1..<8) { index in
                            Text("\(result.daily.temperature2MMin[index])")
                            }
                        }
                    }
                }
            }
            
        }.onAppear() {
            WeatherService().getDate { (results) in
                self.results = results
                print("Check point")
            }
        }
    }
}

----气象服务

class WeatherService : ObservableObject{

    @Published var results = [WeatherModel]()
    
    let urlapi = "https://api.open-meteo.com/v1/forecast?latitude=52.40&longitude=13.07&daily=weathercode,temperature_2m_max,temperature_2m_min&current_weather=true&past_days=1&timezone=Europe%2FBerlin"
     //    let url = "https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&current_weather=true"
    
    func getDate(completion: @escaping ([WeatherModel]) -> ()){
        guard let url = URL(string: urlapi) else {
                    print("Invalid url...")
                    return
                }
        
        URLSession.shared.dataTask(with: url) { data, response, error in
              let results = try! JSONDecoder().decode(WeatherModel.self, from: data!)
              print(results)
              DispatchQueue.main.async {
                  completion([results])
              }
          }.resume()
          
     }   
}

相关问题