Beim Erstellen einer GET
Anfrage gibt es keinen Textkörper für die Anfrage, sondern alles geht über die URL. Sie können auch eine URL erstellen (und den Prozentsatz, der ihr entgeht) URLComponents
.
var url = URLComponents(string: "https://www.google.com/search/")!
url.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]
Der einzige Trick besteht darin, dass für die meisten Webdienste ein +
prozentualer Escapezeichen erforderlich ist (da dies als Leerzeichen gemäß der application/x-www-form-urlencoded
Spezifikation interpretiert wird ). Aber URLComponents
wird nicht Prozent davon entkommen. Apple behauptet, dass dies +
ein gültiges Zeichen in einer Abfrage ist und daher nicht maskiert werden sollte. Technisch gesehen sind sie richtig, dass es in einer Abfrage eines URI erlaubt ist, aber es hat eine besondere Bedeutung in application/x-www-form-urlencoded
Anfragen und sollte wirklich nicht ohne Flucht übergeben werden.
Apple räumt ein, dass wir den +
Zeichen prozentual entkommen müssen , rät jedoch, dies manuell zu tun:
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")
Dies ist eine unelegante Problemumgehung, die jedoch funktioniert. Apple empfiehlt, wenn Ihre Abfragen möglicherweise ein +
Zeichen enthalten und Sie einen Server haben, der sie als Leerzeichen interpretiert.
Wenn Sie das mit Ihrer sendRequest
Routine kombinieren , erhalten Sie so etwas wie:
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()
}
Und du würdest es so nennen:
sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
guard let responseObject = responseObject, error == nil else {
print(error ?? "Unknown error")
return
}
}
Persönlich würde ich JSONDecoder
heutzutage verwenden und einen benutzerdefinierten struct
anstelle eines Wörterbuchs zurückgeben, aber das ist hier nicht wirklich relevant. Hoffentlich veranschaulicht dies die Grundidee, wie die Parameter in die URL einer GET-Anforderung prozentual codiert werden.
Siehe vorherige Überarbeitung dieser Antwort für Swift 2 und manuelle prozentuale Fluchtversuche.
extension string
mit den Werten macht? Auch wann müsste ichHttpBody
dann verwenden?&
trennt ein Parameter vom nächsten. Wenn&
der Wert also auftritt, können Sie ihn nicht ohne Flucht lassen). In Bezug aufHTTPBody
sollten Sie es nicht inGET
Anfrage verwenden; Es wird inPOST
aber nicht verwendetGET
.NSMutableURLRequest
, und weist darauf hin, dass mehr dahinter steckt, als das OP vorschlägt.NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: nil)
?parameters
eine Reihe von Wörterbüchern sein[String: String]
Verwenden Sie NSURLComponents, um Ihre NSURL wie folgt zu erstellen
var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")! urlComponents.queryItems = [ NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)), NSURLQueryItem(name: "z", value: String(6)) ] urlComponents.URL // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6
quelle
Ich benutze dies, versuche es auf dem Spielplatz. Definieren Sie die Basis-URLs als Struktur in Konstanten
struct Constants { struct APIDetails { static let APIScheme = "https" static let APIHost = "restcountries.eu" static let APIPath = "/rest/v1/alpha/" } } private func createURLFromParameters(parameters: [String:Any], pathparam: String?) -> URL { var components = URLComponents() components.scheme = Constants.APIDetails.APIScheme components.host = Constants.APIDetails.APIHost components.path = Constants.APIDetails.APIPath if let paramPath = pathparam { components.path = Constants.APIDetails.APIPath + "\(paramPath)" } if !parameters.isEmpty { components.queryItems = [URLQueryItem]() for (key, value) in parameters { let queryItem = URLQueryItem(name: key, value: "\(value)") components.queryItems!.append(queryItem) } } return components.url! } let url = createURLFromParameters(parameters: ["fullText" : "true"], pathparam: "IN") //Result url= https://restcountries.eu/rest/v1/alpha/IN?fullText=true
quelle
Swift 3 :
extension URL { func getQueryItemValueForKey(key: String) -> String? { guard let components = NSURLComponents(url: self, resolvingAgainstBaseURL: false) else { return nil } guard let queryItems = components.queryItems else { return nil } return queryItems.filter { $0.name.lowercased() == key.lowercased() }.first?.value } }
Ich habe es verwendet, um den Bildnamen für
UIImagePickerController
in zu erhaltenfunc imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
:var originalFilename = "" if let url = info[UIImagePickerControllerReferenceURL] as? URL, let imageIdentifier = url.getQueryItemValueForKey(key: "id") { originalFilename = imageIdentifier + ".png" print("file name : \(originalFilename)") }
quelle
Sie können Ihre verlängern
Dictionary
nur zu liefern ,stringFromHttpParameter
wenn beide Schlüssel und Wert entsprechenCustomStringConvertable
mag dieseextension Dictionary where Key : CustomStringConvertible, Value : CustomStringConvertible { func stringFromHttpParameters() -> String { var parametersString = "" for (key, value) in self { parametersString += key.description + "=" + value.description + "&" } return parametersString } }
Dies ist viel sauberer und verhindert versehentliche Aufrufe
stringFromHttpParameters
von Wörterbüchern, die diese Methode nicht aufrufen könnenquelle
Diese von @Rob vorgeschlagene Erweiterung funktioniert für Swift 3.0.1
Ich konnte die Version, die er in seinen Beitrag aufgenommen hat, nicht mit Xcode 8.1 (8B62) kompilieren.
extension Dictionary { /// Build string representation of HTTP parameter dictionary of keys and objects /// /// :returns: String representation in the form of key1=value1&key2=value2 where the keys and values are percent escaped func stringFromHttpParameters() -> String { var parametersString = "" for (key, value) in self { if let key = key as? String, let value = value as? String { parametersString = parametersString + key + "=" + value + "&" } } parametersString = parametersString.substring(to: parametersString.index(before: parametersString.endIndex)) return parametersString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)! } }
quelle
Ich benutze:
let dictionary = ["method":"login_user", "cel":mobile.text! "password":password.text!] as Dictionary<String,String> for (key, value) in dictionary { data=data+"&"+key+"="+value } request.HTTPBody = data.dataUsingEncoding(NSUTF8StringEncoding);
quelle