skip to Main Content

data is not showing up on my screen.
I thought my get data function was not working properly, but I can print the results to the console. I also thought it might be a problem with the simulator, but I tested the app on an iPhone. I think I have a problem with the weather model (json). I generated it in the generator. I download data from https://open-meteo.com/. I would like to export the current weather and min and max for the next 7 days. How can I change my json so that my data is displayed in the application. thanks for the help.

_________ 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"
    }
}




I can print my result in terminal, but i cannot display on screen in app. I would like to display my current weather temperature ad temperature for next week.

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]))

2

Answers


  1. Chosen as BEST ANSWER

    I fixed it generally, I can now display the current weather. thanks for the help. I added @Published property, noted the ObservableObject protocol.

    My code:

    _____________WeatherService

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

    _______________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{
                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
                    ForEach(result.daily, id: .id) { day in
                        Text("(day.temperature2MMax)")
                    }
                }
            }.onAppear() {
                WeatherService().getDate { (results) in
                    self.results = results
                    print("Check point")
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

  2. Normally your service would be an EnvironmentKey and the download would be done in .task, e.g.

    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()
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search