在Swift中发送简单的POST,得到" Empty Post"响应

时间:2015-11-03 20:25:43

标签: swift post nsurlsession

我的iOS应用中有注册页面,我试图用Swift编写。我测试的第一件事是发送带有电子邮件地址的POST,这就是我这样做的方式:

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()

但是,我收到一条消息,说明这是一个空帖子。这是上面输出的确切响应:responseString = Optional({"complete":"false","message":"Empty Post"}) 我已经研究过在Swift中发送简单POST的不同方法,这似乎是正确的。我无法看到它有什么问题,或者为什么它会输出一条消息说帖子是空的...除了字符串的格式?

数据库期待"新用户"服务,我只发送一个部分,因为它是一个测试。这可能是问题吗?新用户服务期待:

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

(来自文档)。

我还没有多次使用网络服务。在集思广益之后,我认为这些可能是罪魁祸首:我可能会收到回复,因为我没有立即发送所有数据。我也可能发错了。我可以将其作为文本发送,还是需要将其作为JSON发送?

1 个答案:

答案 0 :(得分:4)

有几个问题:

  1. 您有一行说:

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

    这不符合您的意图。它创建了一个包含四个项目的元组,这些项目由格式字符串和三个值组成,而不是单个格式化的字符串。打印bodyData,您就会明白我的意思。

    您要么使用String(format: ...),要么更容易使用字符串插值。 (请参阅下面的代码段。)

  2. 假设emailAddresspasswordUITextField个对象,请注意text属性是可选的,因此您必须在使用它们之前解开这些选项。看看bodyData字符串,你会看到我的意思。

    我不知道deviceModel是否也是可选的,但如果是,也要打开它。

  3. 您在请求的userPassword参数前面有一个空格。那会使它形成不好。删除该空间。您可以通过删除一堆\"引用来简化该格式字符串。

  4. 您可能应该指定请求的Content-Type。这通常没有必要,但这是一种很好的做法。

  5. 您显然已收到JSON响应,因此您可能需要解析它。

  6. 因此,您可以执行以下操作:

    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()
    

    注意,你真的应该百分之百地逃避你正在添加到正文中的值(特别是,如果值可能包含空格,+&或其他保留字符)。见https://stackoverflow.com/a/28027627/1271826

    如果你不想深入了解这类东西的杂草,可以考虑使用像Alamofire这样的框架来处理这些东西。例如:

    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)
            }
    }