1

I have registration page in my iOS app that I'm trying to write in Swift. The first thing I'm testing out is sending a POST with the email address, this is the way I'm doing so:

var bodyData = ("userEmail=%@\" \" &userPassword=%@\" \"&userDevice=%@\" \"", emailAddress.text, password.text, deviceModel)

    let dataToSend = (bodyData as NSString).dataUsingEncoding(NSUTF8StringEncoding)

            request.HTTPMethod = "POST"
            request.HTTPBody = dataToSend
            let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
                data, response, error in

                if error != nil {
                    print("error=\(error)")
                    return
                }
                // print("response = \(response)")

                let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
                print("responseString = \(responseString)")
            }
            task.resume()

However, I'm getting a message back stating that it was an empty post. This is the exact response from the output above: responseString = Optional({"complete":"false","message":"Empty Post"}) I've researched different ways to send a simple POST in Swift, and this appears to be correct. I can't see anything wrong with it or why it would output a message saying that the post was empty... Except for maybe the format of the string?

The database is expecting multiple things for the "new user" service, and I'm only sending one part due to it being a test. Could this be the issue? The new-user service is expecting:

Service URL : https://test.com/services/new-user/
Required Post Fields:
For New User:
'userEmail'
'userPassword'
'userDevice'

(From the documentation).

I haven't worked with web services much. After brainstorming more I think these may be the culprits: I may be getting the response back because I'm not sending all the data at once. I also may be sending it incorrectly. Can I send it as text or do I need to send it as JSON?

Henry F
  • 4,960
  • 11
  • 55
  • 98
  • It would be helpful to know what the new-user service is expecting on the other end, since it's sending JSON back – spirographer Nov 03 '15 at 20:34
  • 1
    @spirographer Thank you that's true, I'll update my OP now. – Henry F Nov 03 '15 at 20:35
  • try testing something like this `var bodyData = "userEmail=\" \" &userPassword=\" \"&userDevice=\" \""` to see if it can use parameters in this format. The other common format is JSON, and you can easily modify the code to support that too – spirographer Nov 03 '15 at 20:49
  • @spirographer Thank you. I just updated my OP with my new code, though it's having a problem converting that Type to NSData... – Henry F Nov 06 '15 at 18:57

1 Answers1

4

A couple of issues:

  1. You have a line that says:

    var bodyData = ("userEmail=%@\" \" &userPassword=%@\" \"&userDevice=%@\" \"", emailAddress.text, password.text, deviceModel)
    

    That does not do what you intended. It's creating a tuple with four items that consists of a format string and three values, not a single formatted string. Print the bodyData and you'll see what I mean.

    You either want to use String(format: ...), or even easier, use string interpolation. (See code snippet below.)

  2. Assuming that emailAddress and password are UITextField objects, note that the text property is optional, so you have to unwrap those optionals before you use them. Look at the bodyData string and you'll see what I mean.

    I don't know if deviceModel was optional as well, but if so, unwrap that, too.

  3. You have a space right before the userPassword parameter of the request. That will make it not well formed. Remove that space. You can probably simplify that format string by getting rid of a bunch of those \" references, too.

  4. You probably should be specifying the Content-Type of the request. It's often not necessary, but it's good practice.

  5. You're clearly getting a JSON response, so you might want to parse it.

Thus, you might do something like:

guard emailAddress.text != nil && password.text != nil else {
    print("please fill in both email address and password")
    return
}

// use 
//
// let bodyString = String(format: "userEmail=%@&userPassword=%@&userDevice=%@", emailAddress.text!, password.text!, deviceModel)
//
// or use string interpolation, like below:

let bodyString = "userEmail=\(emailAddress.text!)&userPassword=\(password.text!)&userDevice=\(deviceModel)"

let bodyData = bodyString.dataUsingEncoding(NSUTF8StringEncoding)

request.HTTPMethod = "POST"
request.HTTPBody = bodyData
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
    guard error == nil && data != nil else {
        print("error=\(error)")
        return
    }

    do {
        let responseObject = try NSJSONSerialization.JSONObjectWithData(data!, options: [])

        print(responseObject)
    } catch let parseError as NSError {
        print(parseError)
    }
}
task.resume()

Note, you really should be percent-escaping the values you are adding to the body, too (notably, if the values might have spaces, +, &, or other reserved characters in them). See https://stackoverflow.com/a/28027627/1271826.

If you don't want to get into the weeds of this sort of stuff, consider using a framework like Alamofire, which takes care of this stuff for you. For example:

guard emailAddress.text != nil && password.text != nil else {
    print("please fill in both email address and password")
    return
}

let parameters = [
    "userEmail" : emailAddress.text!,
    "userPassword" : password.text!,
    "userDevice" : deviceModel
]

Alamofire.request(.POST, urlString, parameters: parameters)
    .responseJSON { response in
        switch response.result {
        case .Failure(let error):
            print(error)
        case .Success(let value):
            print(value)
        }
}
Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thank you so much @Rob! I really appreciate you taking the time to explain this in depth as well. – Henry F Nov 06 '15 at 20:39