Khi xây dựng một GETyêu cầu, không có nội dung nào đối với yêu cầu mà thay vào đó, mọi thứ đều đi trên URL. Để tạo một URL (và phần trăm thoát nó một cách chính xác), bạn cũng có thể sử dụng URLComponents.
var url = URLComponents(string: "https://www.google.com/search/")!
url.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]
Mẹo duy nhất là hầu hết các dịch vụ web cần +phần trăm ký tự được thoát ra (bởi vì chúng sẽ diễn giải đó là một ký tự khoảng trắng theo quy định của application/x-www-form-urlencodedđặc tả ). Nhưng URLComponentssẽ không phần trăm thoát khỏi nó. Apple cho rằng đó +là một ký tự hợp lệ trong một truy vấn và do đó không nên thoát. Về mặt kỹ thuật, họ đúng, nó được cho phép trong một truy vấn của URI, nhưng nó có ý nghĩa đặc biệt trong application/x-www-form-urlencodedcác yêu cầu và thực sự không nên được chuyển đi mà không thoát.
Apple thừa nhận rằng chúng tôi phải thoát các +ký tự phần trăm , nhưng khuyên chúng tôi nên làm điều đó theo cách thủ công:
var url = URLComponents(string: "https://www.wolframalpha.com/input/")!
url.queryItems = [
URLQueryItem(name: "i", value: "1+2")
]
url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
Đây là một công việc không phù hợp, nhưng nó hoạt động và là những gì Apple khuyên nếu các truy vấn của bạn có thể bao gồm một +ký tự và bạn có một máy chủ giải thích chúng là khoảng trắng.
Vì vậy, kết hợp điều đó với sendRequestthói quen của bạn , bạn sẽ có một cái gì đó như:
func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
var components = URLComponents(string: url)!
components.queryItems = parameters.map { (key, value) in
URLQueryItem(name: key, value: value)
}
components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
let request = URLRequest(url: components.url!)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
(200 ..< 300) ~= response.statusCode,
error == nil else {
completion(nil, error)
return
}
let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
completion(responseObject, nil)
}
task.resume()
}
Và bạn sẽ gọi nó như sau:
sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
guard let responseObject = responseObject, error == nil else {
print(error ?? "Unknown error")
return
}
}
Cá nhân tôi, JSONDecoderngày nay tôi muốn sử dụng và trả về một tùy chỉnh structhơn là một từ điển, nhưng điều đó không thực sự phù hợp ở đây. Hy vọng rằng điều này minh họa ý tưởng cơ bản về cách mã hóa phần trăm các tham số thành URL của một yêu cầu GET.
Xem bản sửa đổi trước của câu trả lời này cho Swift 2 và các phiên bản thoát phần trăm thủ công.
extension stringđang làm với các giá trị? Ngoài ra khi nào tôi cần sử dụngHttpBodysau đó?