457 Stimmen

Wie man in Swift eine HTTP-Anfrage stellt?

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?

659voto

Cezar Punkte 54048

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.

105voto

Bijan Punkte 24044

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)
          }

53voto

Suhit Patil Punkte 11098

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)

22voto

Ben Sullivan Punkte 2025

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()

19voto

swiftBoy Punkte 34715

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

  1. Einfache GET-Anfrage mit URL
  2. Einfache GET-Anfrage mit URL und Parametern
  3. Einfache GET-Anfrage mit URL mit Fehlerbehandlungen
  4. 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!!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X