我在iBooks上读了苹果的编程语言Swift,但不知道如何在Swift中发出HTTP请求(类似cURL)。我需要导入Obj-C类还是只需要导入默认库?或者不能基于原生Swift代码进行HTTP请求?


当前回答

基本的Swift 3+解决方案

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

其他回答

下面是在Linux上使用Swift进行HTTP请求的从头到尾的说明。

首先创建一个SwiftPM包

mkdir swift-http && cd swift-http && swift package init --type executable

然后替换。/Sources/swift-http/main.swift 代码如下:

import Foundation
import FoundationNetworking

let sema = DispatchSemaphore(value: 0)

URLSession.shared.dataTask(with: URL(string: "http://numbersapi.com/42")!) {(data, response, error) in
    print(String(data: data!, encoding: .utf8) ?? String(describing: error))
    sema.signal()
}.resume()

sema.wait()

然后运行代码

swift run

输出的例子:

[6/6] Build complete!
42 is the answer to the Ultimate Question of Life, the Universe, and Everything.

注意:使用DispatchSemaphore是为了使程序在得到响应之前不会退出。

你也可以这样做:

import Foundation
import FoundationNetworking

var done = false

URLSession.shared.dataTask(with: URL(string: "http://numbersapi.com/42")!) {(data, response, error) in
    print(String(data: data!, encoding: .utf8) ?? String(describing: error))
    done = true
}.resume()

while !done { Thread.sleep(forTimeInterval: 1) }

另一个选择是Alamofire库,它提供了可链请求/响应方法。

https://github.com/Alamofire/Alamofire

提出请求

import Alamofire

Alamofire.request(.GET, "http://httpbin.org/get")

响应处理

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
         .response { request, response, data, error in
              print(request)
              print(response)
              print(error)
          }

下面是一个非常简单的Swift 4在操场上的例子:

import UIKit
// run asynchronously in a playground
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

// create a url
let url = URL(string: "http://www.stackoverflow.com")

// create a data task
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
    if error != nil {
        print("there's a problem")
    }
    print(String(data: data!, encoding: String.Encoding.utf8) ?? "")
}

//running the task w/ resume
task.resume()

为了让XCUITest在异步请求完成之前停止测试完成,使用这个(可能会减少100超时):

func test_api() {
    let url = URL(string: "https://jsonplaceholder.typicode.com/posts/42")!
    let exp = expectation(description: "Waiting for data")
    let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
        guard let data = data else { return }
        print(String(data: data, encoding: .utf8)!)
        exp.fulfill()
    }
    task.resume()
    XCTWaiter.wait(for: [exp], timeout: 100)
}

更新:Xcode 13.0和Swift 5+

获取HTTP请求

let url = URL(string: "URL HERE")! //PUT Your URL
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let safeData = data,
                  let response = response as? HTTPURLResponse,
                  error == nil else {                                              // check for fundamental networking error
                      print("error", error ?? "Unknown error")
                      delegate?.onError(error!)
                      return
                  }
            
            guard (200 ... 299) ~= response.statusCode else {                    // check for http errors
                print("statusCode should be 2xx, but is \(response.statusCode)")
                print("response = \(response)")
                return
            }
            
            let responseString = String(data: safeData, encoding: .utf8)
            print("Response String = \(responseString)")
        }
        
        task.resume()