3

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?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
RPP
  • 55
  • 6
  • possible duplicate of [How can I get the Data from NSURLSession.sharedSession().dataTaskWithRequest](http://stackoverflow.com/questions/31264172/how-can-i-get-the-data-from-nsurlsession-sharedsession-datataskwithrequest) – Eric Aya Aug 21 '15 at 08:50
  • 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 Aug 21 '15 at 08:52
  • @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 Aug 21 '15 at 09:08

2 Answers2

1

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"
})
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
0

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

Mihir Mehta
  • 13,743
  • 3
  • 64
  • 88
  • @Eric for whatever type i am creating it give the same message json is not convertible to that type. //@mihir if you can provide an example that would really help to clear my doubts. – RPP Aug 21 '15 at 09:36
  • can you add code from where you're calling this method and also highlight the line that gives you this error ? – Mihir Mehta Aug 21 '15 at 09:37
  • `callWeatherServ(name, completion: { (responseDictionary) -> Void in // use responseDictionary here println(responseDictionary) }) `` let json = JSON(jsonResult) println("response is \(json) ") var weathername:Dictionary = json["weather"][0]["main"] if (weathername != nil) { completion(weathername) }` this is the way i ma trying to changes the type as suggested by eric – RPP Aug 21 '15 at 09:53
  • @RichaPathak you cannot return from a method which has return type as void. – Mihir Mehta Aug 21 '15 at 10:16