从Swift发出POST请求

时间:2019-06-06 14:42:12

标签: json swift

基本上,我需要向正在寻找"value"的参数值的API发送POST请求,我的Swift应用程序中有一个名为testPOST的变量,其中包含API所寻找的值:< / p>

我无法理解以下代码为何不起作用?

fileprivate func fetchJSON(){
    var urlString =  URLRequest(url: URL(string: "https://example.com/example/example.php")!)
    guard let url = URL(string: urlString) else { return }
    urlString.httpMethod = "POST"
    let postString = "value=\(testPOST)"
    URLRequest.httpBody = postString.data(using: .utf8)
    URLSession.shared.dataTask(with: url) { (data, _, error) in
        DispatchQueue.main.async {
            if let error = error {
                print("Failed to fetch data from url", error)
                return
            }
            guard let data = data else { return }
            do {
                let decoder = JSONDecoder()
                // Swift 4.1

                self.structure = try decoder.decode([ScheduleStructure].self, from: data)

                self.tableView.reloadData()

            } catch let jsonError {
                print("Failed to decode json", jsonError)
            }

        }
        }.resume()
}

更新:

我没有收到任何错误消息,但是我也没有收到任何JSON数据,ScheduleStructure是我拥有的可编码结构,但似乎无法读取。

导入UIKit

struct ScheduleStructure: Codable {
    let customer: String
    let PickedUpNUM: String
    let DeliveryNUM: String

}

我只需要一种将值发布到API并使其返回JSON数据的方法。我唯一遇到的问题是从应用发送数据并返回数据。

2 个答案:

答案 0 :(得分:3)

将函数的开头更改为

guard let url = URL(string: "https://example.com/example/example.php") else {
    return
}
var request =  URLRequest(url: url)
request.httpMethod = "POST"
let postString = "value=\(testPOST)"
request.httpBody = postString.data(using: .utf8)
URLSession.shared.dataTask(with: request) { (data, _, error) in

您两次创建了url对象,并将请求视为字符串

答案 1 :(得分:1)

您应该随时接受Joakim’s answer,它标识了句法问题,但是我想再说一遍。具体来说,如果testPOST包含任何保留字符(例如空格,&+等),您的请求将失败或无法正常工作。除非您知道testPOST绝不能包含任何此类字符,否则应在构建请求时对值进行百分比编码,例如:

func fetchJSON() {
    guard
        let url = URL(string: "https://example.com/example/example.php"),
        let value = testPOST.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
    else { return }

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = "value=\(value)".data(using: .utf8)

    URLSession.shared.dataTask(with: request) { data, _, error in
        DispatchQueue.main.async {
            // ...
        }
    }.resume()
}

哪里

extension CharacterSet {
    static let urlQueryValueAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="

        var allowed = CharacterSet.urlQueryAllowed
        allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
        return allowed
    }()
}

顺便说一句,最好的做法(虽然通常不是必需的)是设置一些标头,特别是Content-Type(指定请求的编码方式)和Accept(客户端期望响应如何)编码)。

request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")

您的Web服务显然没有考虑这些标头,但是许多Web服务却在考虑。另外,它使您的代码意图明确。