【问题标题】:Sending simple POST in Swift, getting "Empty Post" response在 Swift 中发送简单的 POST,得到“Empty Post”响应
【发布时间】:2015-11-03 20:25:43
【问题描述】:

我的 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'

(来自文档)。

我没有过多地使用 Web 服务。在进行了更多头脑风暴之后,我认为这些可能是罪魁祸首:我可能会收到回复,因为我没有一次发送所有数据。我也可能发送不正确。我可以以文本形式发送还是需要以 JSON 形式发送?

【问题讨论】:

  • 了解新用户服务在另一端的期望会很有帮助,因为它正在发回 JSON
  • @spirographer 谢谢你,这是真的,我现在就更新我的 OP。
  • 尝试测试类似var bodyData = "userEmail=\" \" &userPassword=\" \"&userDevice=\" \"" 的东西,看看它是否可以使用这种格式的参数。另一种常见格式是 JSON,您也可以轻松修改代码以支持它
  • @spirographer 谢谢。我刚刚用我的新代码更新了我的 OP,虽然在将该类型转换为 NSData 时遇到问题...

标签: swift post nsurlsession


【解决方案1】:

几个问题:

  1. 你有一行说:

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

    这并没有达到您的预期。它正在创建一个包含四个项目的元组,这些项目由一个格式字符串和三个值组成,而不是一个单一的格式化字符串。打印bodyData,你就会明白我的意思了。

    您要么想使用String(format: ...),要么更简单,使用字符串插值。 (参见下面的代码 sn-p。)

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

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

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

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

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

因此,您可能会执行以下操作:

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

【讨论】:

  • 非常感谢@Rob!我也非常感谢您花时间深入解释这一点。
猜你喜欢
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 2023-02-01
  • 2018-08-01
相关资源
最近更新 更多