0

I have a separate class for all my json api requests calls: userJson.swift

I want to have functions in here that return the json so I can work with the json in my controllers. This is one of my functions in it:

func signIn(email: String, username: String, password: String){

    var request : NSMutableURLRequest = NSMutableURLRequest()
    request.URL = NSURL(string: signUpURL)
    request.HTTPMethod = "POST"
    let body = "email=\(email)&username=\(username)&password=\(password)"
    request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
        {
            data, response, error in

            if (error != nil) {
                return error
            } else {
                let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

                return json
            }
    }

    task.resume()

}

I want to return json but it gives me an error: 'NSDictionary' is not convertible to 'Void'. How can I just return the json so I can work with it in my controller?

Laurenswuyts
  • 2,144
  • 4
  • 21
  • 39
  • Have you examined data? – zaph Feb 15 '15 at 16:06
  • 1
    BTW, make sure you percent escape the values you pass in the body of your request. If the password has, for example, a `+` or `&` character in it, the above would not work. See http://stackoverflow.com/a/25154803/1271826 – Rob Feb 15 '15 at 17:49

1 Answers1

1

The approach you are using is not correct since:

  1. the signIn function returns Void

Here you want to return an object that can be a dictionary or an error.

  1. The method dataTaskWithRequest is performed in a async fashion. So, the return will give you a non-valuable result.

When I talk of async fashion code I mean a pattern like the following:

  • signIn functions gets called
  • dataTaskWithRequest gets called
  • signIn function finishes
  • the completion handler of dataTaskWithRequest is invoked

You have to change a little bit the signature of your signIn method in order to take this into consideration. For example taking advantage of closure mechanism like the following (the code I provided is just for illustrative purposes).

func signIn(email: String, username: String, password: String, completionHandler: ((AnyObject?, NSError?) -> Void)) {

    var request : NSMutableURLRequest = NSMutableURLRequest()
    request.URL = NSURL(string: signUpURL)
    request.HTTPMethod = "POST"

    let body = "email=\(email)&username=\(username)&password=\(password)"
    request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
        {
            data, response, error in

            if (error != nil) {
                completionHandler(nil, error)
            } else {
                let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
                completionHandler(data, nil)
            }
        }

    task.resume()
}

Usage

signIn("email", username: "username", password: "password") { (json, error) -> Void in
    if let er = error {
        println("\(er)")
    }                
}
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190