Search code examples
iosjsonswift

Can't get data from Dark Sky API


I try to get information about the weather hourly from the Dark Sky API, but the code stops working at the if let data = hourly["data"] as? [String : AnyObject] line (checked with printing stuff after every line). I want to know what is wrong with my code. I think it could be something with the "data" let, but I don't know for sure.

 let Task2 = URLSession.shared.dataTask(with: urlRequestDark) { (data, response, error) in
        if error == nil {
            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
                
                if let hourly = json["hourly"] as? [String : AnyObject] {
                    if let data = hourly["data"] as? [String : AnyObject]{
                        
                        
                        if let hourNum = data["14"] as? [String : AnyObject] {
                            if let chanceRain = hourNum["precipProbability"] as? Float{
                                self.chanceHour1 = String(chanceRain)
                            }
                            DispatchQueue.main.sync {
                                self.ChanceRainLabel.text = self.chanceHour1
                            }
                        }
                    }
                    
                }
                
            } catch let jsonError {
                print(jsonError.localizedDescription)
            }
        }
    }
    Task2.resume() test

The strange part is, this does work:

let urlRequestDark = URLRequest(url: URL (string: "https://api.darksky.net/forecast/(API Key)/(coordinates)")!)
    
    let Task = URLSession.shared.dataTask(with: urlRequestDark) { (data, response, error) in
        if error == nil {
            do{
                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]

                
                if let currently = json["currently"] as? [String : AnyObject] {
                    
                    if let chance2 = currently["precipProbability"] as? Float{
                        print(String(chance2))
                        self.chance = String(Int(chance2 * 100)) + "%"
                        self.PreType = currently["precipType"] as? String
                    }
            
                        if let _ = json["error"]{
                    }
                    
                    DispatchQueue.main.sync{
                        self.TypeLabel.text = self.PreType
                        self.ChanceLabel.text = self.chance
                    }
                }
                
            
            }catch let jsonError{
                print(jsonError.localizedDescription)
            }
        }
    }
    Task.resume()

Solution

  • You've made couple mistakes.

    First, "data" is an array of dictionaries, so it should be cast to [[String : AnyObject]].

    Second, you're trying to subscript array by String, not Int.

    Third, using self in escaping closures potentially creates retain cycles.

    Let me propose you some fixed and adjusted code.

    let task2 = URLSession.shared.dataTask(with: urlRequestDark) { [weak self] (data, response, error) in
        guard error == nil else { return }
        do {
            if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String : AnyObject],
                let hourly = json["hourly"] as? [String : AnyObject],
                let data = hourly["data"] as? [[String : AnyObject]],
                data.count > 14,
                let chanceRain = data[14]["precipProbability"] as? Float {
                    self?.chanceHour1 = String(chanceRain)
                    DispatchQueue.main.sync {
                        self?.ChanceRainLabel.text = self?.chanceHour1
                    }
            }
        } catch let jsonError {
            print(jsonError.localizedDescription)
        }
    }
    task2.resume()