0

I'm trying to make an async API get request to openweathermap.org 's API. The result should be this JSON structure. I'm particularly trying to get the temperature. I was taught to work with it by wrapping the JSON to a dictionary. Thing is I don't know what I can use to specify the object "main" (in the JSON) and get the temperature. Do I have to iterate object by object? This is my code so far (side note: is it worrying that my app uses 50 mb of RAM?)

let url = URL(string: stringURL)

    let myQ = DispatchQueue.init(label: "getCityDetails")
    myQ.async {

        let session = URLSession.shared
        let m = session.dataTask(with: url!, completionHandler: {(data, response, error) in
            if let error = error {
                print(error.localizedDescription)
                return
            }

            guard let httpResponse = response as? HTTPURLResponse,
                (200...299).contains(httpResponse.statusCode) else {
                    print("Error with the response, unexpected status code: \(String(describing: response))")
                    return
            }

            do {
                if let d = data{
                    let dictionaryObj =  try JSONSerialization.jsonObject(with: d, options: []) as! NSDictionary
                    print(dictionaryObj)
                }
            }catch{
                print(error.localizedDescription)
            }

        })
        m.resume()
1
  • 1
    Try that the code that you attach to the answer compiles :) Commented Apr 18, 2020 at 9:36

1 Answer 1

1

The first point is that the default URLSession works in a background thread so you dont need to create a dispatch queue (alos you are not using it correctly). The second point tries to use optional data not to use try/catch. Finally you could try to use Swift 5 together to the protocol Codable to have better code, simple and secure.

let url = URL(string: "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=439d4b804bc8187953eb36d2a8c26a02")!
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
    if let error = error {
        print(error.localizedDescription)
        return
    }

    guard let httpResponse = response as? HTTPURLResponse,
        (200...299).contains(httpResponse.statusCode) else {
            print("Error with the response, unexpected status code: \(String(describing: response))")
            return
    }

    guard let data = data else {
        return
    }

    guard let dictionaryObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
        return
    }
    if let main = dictionaryObj["main"] as? [String: Any], let temperature = main["temp"] {
        DispatchQueue.main.async {
            print("Temperature: \(temperature)")
        }
    }
}).resume()
Sign up to request clarification or add additional context in comments.

3 Comments

It works! Thanks. I realize I don't need to use Dispatch.main.async when fetching the JSON, but why do I need to use it while printing temperature? something so simple, it seems unnecessary to use another thread
I added the main thread when the temperature is printed because normally the data is downloaded and processed in background and the UI is updated in the main thread. But if you are not updating any UI you can remove it.
Please don't forget to mark the answer how resolved :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.