Khi xây dựng một GET
yê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 URLComponents
sẽ 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-urlencoded
cá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 sendRequest
thó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, JSONDecoder
ngày nay tôi muốn sử dụng và trả về một tùy chỉnh struct
hơ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ụngHttpBody
sau đó?