Search code examples
jsonswiftnsjsonserializationopenweathermap

String Value and Weather Icon in OpenWeatherMap


I am trying to retrieve the Main and Description form the value but it does not show up in the UILabel. All other parameters show up well. Like Temperature and Max and Min Temp Wind speed and direction. I am also having difficulties with weather icon and need some guidance if my code is right.

import UIKit
import Foundation

class ViewController: UIViewController {
    var timer = Timer()

    struct CurrentLocalWeather: Codable {
        let base: String
        let clouds: Clouds
        let cod: Int
        let coord: Coord
        let dt: Int
        let id: Int
        let main: Main
        let name: String
        let sys: Sys
        let visibility: Int
        let weather: Weather
        let wind: Wind
    }

    struct Clouds: Codable {
        let all: Int
    }

    struct Coord: Codable {
        let lat: Double
        let lon: Double
    }

    struct Main: Codable {
        let humidity: Int
        let pressure: Int
        let temp: Double
        let tempMax: Double
        let tempMin: Double
        private enum CodingKeys: String, CodingKey {
            case humidity, pressure, temp, tempMax = "temp_max", tempMin = "temp_min"
        }
    }

    struct Sys: Codable {
        let country: String
        let id: Int
        let message: Double
        let sunrise: UInt64
        let sunset: UInt64
        let type: Int
    }

    struct Weather: Codable {
        let description: String
        let icon: String
        let id: Int
        let main: String
    }

    struct Wind: Codable {
        let deg: Int
        let speed: Double
    }

    //Variables from Storyboard
    @IBOutlet weak var Temp: UILabel!
    @IBOutlet weak var TempMin: UILabel!
    @IBOutlet weak var TempMax: UILabel!
    @IBOutlet weak var WindSpeed: UILabel!
    @IBOutlet weak var Direction: UILabel!
    @IBOutlet weak var Humidity: UILabel!
    @IBOutlet weak var MainDesc: UILabel!
    @IBOutlet weak var Description: UILabel!
    @IBOutlet weak var City: UILabel!
    @IBOutlet weak var SunRise: UILabel!
    @IBOutlet weak var SunSet: UILabel!
    @IBOutlet weak var Icon: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Define URL for Weather Data
        URLSession.shared.dataTask(with: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=51.05011&lon=-114.08529&appid=<APPID_REMOVED_FOR_POSTING_PURPOSE>&units=metric")!) { data, response, error in
            if let error = error {
                print("Error:\n\(error)")
            } else {
                do {
                    let JSon = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]

                    if let Temp1 = JSon["weather"]as? NSDictionary {
                        DispatchQueue.main.async {
                            self.Description.text = Temp1["description"] as? String
                            self.MainDesc.text = Temp1["main"] as? String
                        let Ico = (Temp1["icon"] as? String)!
                            let Icon = UIImageView()
                            let urlStr = NSURL(string:"http://openweathermap.org/img/w/\(Ico).png")
                            let urlData = NSData(contentsOf: urlStr! as URL)
                            if urlData == nil {
                                Icon.image = UIImage(data: urlData! as Data)
                            }
                        }
                    }
} catch let jsonError as NSError {
                    print("JSON error:\n\(jsonError.description)")
                }
            }
            }.resume()
}

This is the result from the query:

{"coord":{"lon":-114.09,"lat":51.05},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"stations","main":{"temp":10.9,"pressure":1014,"humidity":32,"temp_min":8.89,"temp_max":13.33},"visibility":56326,"wind":{"speed":11.3,"deg":20},"clouds":{"all":40},"dt":1556142366,"sys":{"type":1,"id":989,"message":0.0068,"country":"CA","sunrise":1556108578,"sunset":1556160342},"id":5913490,"name":"Calgary","cod":200}


Solution

  • I was able to solve the issue for the string value not showing up by making the below changes.

    Import UIKit
    import Foundation
    
    class ViewController: UIViewController {
        var timer = Timer()
    
    
        //Variables from Storyboard
        @IBOutlet weak var Temp: UILabel!
        @IBOutlet weak var TempMin: UILabel!
        @IBOutlet weak var TempMax: UILabel!
        @IBOutlet weak var WindSpeed: UILabel!
        @IBOutlet weak var Direction: UILabel!
        @IBOutlet weak var Humidity: UILabel!
        @IBOutlet weak var MainDesc: UILabel!
        @IBOutlet weak var Description: UILabel!
        @IBOutlet weak var City: UILabel!
        @IBOutlet weak var SunRise: UILabel!
        @IBOutlet weak var SunSet: UILabel!
        @IBOutlet weak var Icon: UIImageView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Define URL for Weather Data
            URLSession.shared.dataTask(with: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=51.05011&lon=-114.08529&appid=<APPID_REMOVED_FOR_POSTING_PURPOSE>&units=metric")!) { data, response, error in
                if let error = error {
                    print("Error:\n\(error)")
                } else {
                    do {
                        let JSon = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
    
                        let weatherData = (JSon["weather"]as! NSArray)
                        if let Temp1 = weatherData[0] as? NSDictionary {
                            DispatchQueue.main.async {
                                self.Description.text = Temp1["description"] as? String
                                self.MainDesc.text = Temp1["main"] as? String
                            let Ico = (Temp1["icon"] as? String)!
                                let urlStr = NSURL(string:"http://openweathermap.org/img/w/\(Ico).png")
                                let urlData = NSData(contentsOf: urlStr! as URL)
                                if urlData != nil {
                                    self.Icon.image = UIImage(data: urlData! as Data)
                                }
                            }
                        }
    } catch let jsonError as NSError {
                        print("JSON error:\n\(jsonError.description)")
                    }
                }
                }.resume()
    }
    

    I am still stuck with getting the icon to work hopefully i should be able to post that as well. for folks who tried using Codable and got it right please share.