Ich habe "Die Programmiersprache Swift" von Apple in iBooks gelesen, kann aber nicht herausfinden, wie man in Swift eine HTTP-Anfrage (etwas ähnliches wie cURL) erstellt. Muss ich Obj-C-Klassen importieren oder reicht es aus, Standardbibliotheken zu importieren? Oder ist es nicht möglich, basierend auf nativem Swift-Code eine HTTP-Anfrage zu erstellen?
Antworten
Zu viele Anzeigen?Sie können URL
, URLRequest
und URLSession
oder NSURLConnection
verwenden, wie Sie es normalerweise in Objective-C tun würden. Beachten Sie, dass ab iOS 7.0 URLSession
bevorzugt wird.
Verwendung von URLSession
Initialisieren Sie ein URL
-Objekt und ein URLSessionDataTask
aus URLSession
. Führen Sie dann die Aufgabe mit resume()
aus.
let url = URL(string: "http://www.stackoverflow.com")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
task.resume()
Verwendung von NSURLConnection
Initialisieren Sie zunächst ein URL
und ein URLRequest
:
let url = URL(string: "http://www.stackoverflow.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
Dann können Sie die Anfrage asynchron laden mit:
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {(response, data, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
Oder Sie können eine NSURLConnection
initialisieren:
let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)
Stellen Sie einfach sicher, dass Sie Ihren Delegierten auf etwas anderes als nil
setzen und verwenden Sie die Delegiertenmethoden, um mit der Antwort und den empfangenen Daten zu arbeiten.
Weitere Details finden Sie in der Dokumentation für das NSURLConnectionDataDelegate
Protokoll
Testen auf einem Xcode-Playground
Wenn Sie diesen Code auf einem Xcode-Playground ausprobieren möchten, fügen Sie import PlaygroundSupport
zu Ihrem Playground hinzu, sowie den folgenden Aufruf:
PlaygroundPage.current.needsIndefiniteExecution = true
Dies ermöglicht es Ihnen, asynchronen Code in Playgrounds zu verwenden.
Eine weitere Option ist die Alamofire Bibliothek, die Chainable Request / Response Methoden bietet.
https://github.com/Alamofire/Alamofire
Eine Anfrage stellen
import Alamofire
Alamofire.request(.GET, "http://httpbin.org/get")
Response-Verarbeitung
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.response { request, response, data, error in
print(request)
print(response)
print(error)
}
Swift 4 und höher Datenanforderung mit URLSession API
// Die URL erstellen
let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! // URL ändern
// Das Session-Objekt erstellen
let session = URLSession.shared
// Jetzt das URLRequest-Objekt mit dem URL-Objekt erstellen
let request = URLRequest(url: url)
// dataTask erstellen, um Daten an den Server zu senden, unter Verwendung des Session-Objekts
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
// JSON-Objekt aus den Daten erstellen
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
Swift 5 und höher, Decodable und Result enum
// NetworkError-Enum, die alle möglichen Netzwerkfehler abdeckt
enum NetworkError: Error {
case badURL(String)
case networkError(Error)
case invalidData
case jsonParsingError(DecodingError)
case invalidStatusCode(Int)
case unknown(Error)
}
// dataRequest, das eine Anfrage an die angegebene URL sendet und in ein Decodable-Objekt konvertiert
func dataRequest(with url: String, objectType: T.Type, completion: @escaping (Result) -> Void) {
// Die URL-Instanz erstellen
guard let requestURL = URL(string: url) else {
completion(.failure(APIError.badURL(url))
return
}
// Das Session-Objekt erstellen
let session = URLSession.shared
// Jetzt das URLRequest-Objekt mit dem URL-Objekt erstellen
let request = URLRequest(url: requestURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60)
// dataTask erstellen, um Daten an den Server zu senden, unter Verwendung des Session-Objekts
let task = session.dataTask(with: request, completionHandler: { data, response, error in
// Ergebnistyp deklarieren
let result: Result
// Den Aufruf des Completion-Handlers aufschieben
defer {
completion(result)
}
if let error {
result = .failure(.networkError(error))
return
}
guard let data = data, !data.isEmpty else {
result = .failure(.invalidData)
return
}
do {
// Decodable-Objekt aus den Daten erstellen
let responseObject = try JSONDecoder().decode(responseType.self, from: data)
result = .success(responseObject)
} catch let error as DecodingError {
result = .failure(.jsonParsingError(error))
} catch {
result = .failure(.unknown(error))
}
task.resume()
}
Beispiel:
// Wenn wir eine Aufgabe von der Placeholder-API abrufen möchten, definieren wir die ToDo-Struktur und rufen dataRequest auf und übergeben die Zeichenfolgen-URL "https://jsonplaceholder.typicode.com/todos/1".
struct ToDo: Decodable {
let id: Int
let userId: Int
let title: String
let completed: Bool
}
dataRequest(with: "https://jsonplaceholder.typicode.com/todos/1", objectType: ToDo.self) { (result: Result) in
switch result {
case .success(let object):
print(object)
case .failure(let error):
print(error)
}
}
// das gibt das Ergebnis aus:
ToDo(id: 1, userId: 1, title: "delectus aut autem", completed: false)
Grundlegende Swift 3+ Lösung
guard let url = URL(string: "http://www.stackoverflow.com") else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
print(NSString(data: data, encoding: String.Encoding.utf8.rawValue))
}
task.resume()
Verwendung von URLSession + Swift 5
Nur als Ergänzung zu cezars Antwort, wenn Sie eine Webanfrage mit der URLSession-Klasse von Apple stellen möchten, gibt es mehrere Möglichkeiten, um die Aufgabe zu erledigen
- Einfache GET-Anfrage mit URL
- Einfache GET-Anfrage mit URL und Parametern
- Einfache GET-Anfrage mit URL mit Fehlerbehandlungen
- Einfache POST-Anfrage mit URL, Parametern mit Fehlerbehandlungen
1. Einfache GET-Anfrage mit URL
func simpleGetUrlRequest()
{
let url = URL(string: "https://httpbin.org/get")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
print("Die Antwort ist : ",String(data: data, encoding: .utf8)!)
//print(NSString(data: data, encoding: String.Encoding.utf8.rawValue) as Any)
}
task.resume()
}
Hinweis : Vergewissern Sie sich, dass Sie im pList "NSAppTransportSecurity" Schlüssel für http Anfragen hinzufügen müssen
NSAppTransportSecurity
NSAllowsArbitraryLoads
2. Einfache GET-Anfrage mit URL und Parametern
func simpleGetUrlWithParamRequest()
{
let url = URL(string: "https://www.google.com/search?q=peace")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
if error != nil || data == nil {
print("Client error!")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server error!")
return
}
print("Die Antwort ist : ",response)
}
task.resume()
}
3. Einfache GET-Anfrage mit URL mit Fehlerbehandlungen
func simpleGetUrlRequestWithErrorHandling()
{
let session = URLSession.shared
let url = URL(string: "https://httpbin.org/get")!
let task = session.dataTask(with: url) { data, response, error in
if error != nil || data == nil {
print("Client error!")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server error!")
return
}
guard let mime = response.mimeType, mime == "application/json" else {
print("Falscher MIME-Typ!")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
print("Die Antwort ist : ",json)
} catch {
print("JSON Fehler: \(error.localizedDescription)")
}
}
task.resume()
}
4. Einfache POST-Anfrage mit URL, Parametern mit Fehlerbehandlungen.
func simplePostRequestWithParamsAndErrorHandling(){
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 30
let session = URLSession(configuration: configuration)
let url = URL(string: "https://httpbin.org/post")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let parameters = ["username": "foo", "password": "123456"]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
if error != nil || data == nil {
print("Client error!")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Oops!! es gibt einen Serverfehler!")
return
}
guard let mime = response.mimeType, mime == "application/json" else {
print("Antwort ist kein JSON")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
print("Die Antwort ist : ",json)
} catch {
print("JSON Fehler: \(error.localizedDescription)")
}
})
task.resume()
}
Ihre Vorschläge sind willkommen!!
- See previous answers
- Weitere Antworten anzeigen