3
votes

I am calling Openweather map API using Swift and from the response I need to return a particular value as string.

However when I try to return the value error comes as JSON is not convertible to string.

func callWeatherServ(name:String, completion:(Dictionary<String,AnyObject>) -> Void)
{
    var baseUrl: String = "http://api.openweathermap.org/data/2.5/weather"

    var url: String = "\(baseUrl)?q=\(name)"

    let finalUrl: NSURL = NSURL(string: url)!

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithURL(finalUrl, completionHandler: {data, response, error -> Void in
        if error != nil
        {
            // If there is an error in the web request, print it to the console
            println(error.localizedDescription)
        }

        var err: NSError?
        var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary
        if err != nil
        {
            // If there is an error parsing JSON, print it to the console
            println("JSON Error \(err!.localizedDescription)")
        }

        let json = JSON(jsonResult)
        println("response is \(json) ")

        var  weathername = json["weather"][0]["main"]

        if (weathername != nil)
        {
            return weathername

        }
    })
    task.resume()
}

I get that since we have used closure whose return type void so we should use completion handler. But I am not aware how we can do that.

Also how we can call the function if we pass completion handler as parameter?

2
Do completion(weathername) instead of return weathername then call your function using the completion like in my example link. Also be careful, it seems like you're parsing your JSON twice, once with NSJSONSerialization and once with SwiftyJSON... - Eric Aya
@Eric i am sorry as i could not relate my example with yours as i am new in learning swift .Can you please guide me with my example only . - RPP

2 Answers

1
votes

If you want to keep using SwiftyJSON as in your example, here's how to do it:

  • change the type of the completion handler from a dictionary to the JSON type used by SwiftyJSON.

  • then wrap the value you want to "return" in the handler.

  • then call your method as in my example, with a trailing closure

Swift 2

func callWeatherServ(name:String, completion:(object: JSON) -> Void) {
    let baseUrl: String = "http://api.openweathermap.org/data/2.5/weather"
    let url: String = "\(baseUrl)?q=\(name)"
    if let finalUrl = NSURL(string: url) {
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(finalUrl, completionHandler: {data, response, error -> Void in
            if let error = error {
                print(error.localizedDescription)
            } else {
                if let data = data {
                    let json = JSON(data: data)
                    print("response is \(json) ")
                    completion(object: json["weather"][0]["main"])
                } else {
                    print("No data")
                }
            }
        })
        task.resume()
    }
}

Call the method:

callWeatherServ("paris") { (object) in
    // here you get back your JSON object
    print(object)
}

Note that you were parsing your data twice, with NSJSONSerialization and with SwiftyJSON, so I've removed the unnecessary NSJSONSerialization part.

Original Swift 1 version

func callWeatherServ(name:String, completion:(object: JSON) -> Void)
{
    var baseUrl: String = "http://api.openweathermap.org/data/2.5/weather"

    var url: String = "\(baseUrl)?q=\(name)"

    let finalUrl: NSURL = NSURL(string: url)!

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithURL(finalUrl, completionHandler: {data, response, error -> Void in
        if error != nil
        {
            // If there is an error in the web request, print it to the console
            println(error.localizedDescription)
        }

        var err: NSError?
        let json = JSON(data: data, options: NSJSONReadingOptions.allZeros, error: &err)
        println("response is \(json) ")

        var  weathername = json["weather"][0]["main"]

        if (weathername != nil)
        {
            completion(object: weathername)

        }
    })
    task.resume()
}

Call the method:

callWeatherServ("paris", completion: { (object) -> Void in
    println(object)  // "Clear"
})
0
votes

Implement completion handler from where you are calling this method and use the string at that place only no need to return the string.

You can directly use it from the completion handle by implemet it in caller function