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


当前回答

另一个选择是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及以上:使用URLSession API进行数据请求

   // create the url
   let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! //change the url
        
   // create the session object 
   let session = URLSession.shared
        
   // now create the URLRequest object using the url object
   let request = URLRequest(url: url)
        
   // create dataTask using the session object to send data to the server
   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 {
         //create json object from data
         if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
            print(json)
         }
      } catch let error {
        print(error.localizedDescription)
      }
   })

   task.resume()

Swift 4及以上,可解码和结果enum

// APIError enum which shows all possible Network errors
enum APIError: Error {
    case networkError(Error)
    case dataNotFound
    case jsonParsingError(Error)
    case invalidStatusCode(Int)
    case badURL(String)
}

// Result enum to show success or failure
enum Result<T> {
    case success(T)
    case failure(AppError)
}

// dataRequest which sends request to given URL and convert to Decodable Object
func dataRequest<T: Decodable>(with url: String, objectType: T.Type, completion: @escaping (Result<T>) -> Void) {
    
    // create the url with NSURL
    guard let dataURL = URL(string: url) else {
       completion(.failure(APIError.badURL(url))
       return
    }
    
    // create the session object
    let session = URLSession.shared
    
    // now create the URLRequest object using the url object
    let request = URLRequest(url: dataURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60)
    
    // create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request, completionHandler: { data, response, error in
        
        guard error == nil else {
            completion(Result.failure(APIError.networkError(error!)))
            return
        }
        
        guard let data = data else {
            completion(Result.failure(AppError.dataNotFound))
            return
        }
        
        do {
            // create decodable object from data
            let decodedObject = try JSONDecoder().decode(objectType.self, from: data)
            completion(Result.success(decodedObject))
        } catch let error {
            completion(Result.failure(APIError.jsonParsingError(error as! DecodingError)))
        }
    })
    
    task.resume()
}

例子:

//如果我们想从占位符API获取todo,那么我们定义todo结构体并调用dataRequest并传递“https://jsonplaceholder.typicode.com/todos/1”字符串url。

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

//输出结果:

ToDo(id: 1, userId: 1, title: "delectus aut autem", completed: false)

在Swift 4.1和Xcode 9.4.1中。

JSON POST方法示例。要检查互联网连接,从https://developer.apple.com/library/archive/samplecode/Reachability/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007324-Intro-DontLinkElementID_2添加Reachability.h & .m文件

func yourFunctionName {
    //Check internet connection
    let networkReachability = Reachability.forInternetConnection()
    let networkStatus:Int = (networkReachability?.currentReachabilityStatus())!.rawValue
    print(networkStatus)
    if networkStatus == NotReachable.rawValue {
        let msg = SharedClass.sharedInstance.noNetMsg//Message
        //Call alert from shared class
        SharedClass.sharedInstance.alert(view: self, title: "", message: msg)
    } else {
        //Call spinner from shared class
        SharedClass.sharedInstance.activityIndicator(view: self.view)//Play spinner

        let parameters = "Your parameters here"
        var request = URLRequest(url: URL(string: url)!)

        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"

        print("URL : \(request)")

        request.httpBody = parameters.data(using: .utf8)

        let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil else { // check for fundamental networking error
            //Stop spinner
            SharedClass.sharedInstance.stopActivityIndicator() //Stop spinner
            //Print error in alert
            SharedClass.sharedInstance.alert(view: self, title: "", message: "\(String(describing: error!.localizedDescription))")
            return
            }

            SharedClass.sharedInstance.stopActivityIndicator() //Stop spinner

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }

            do {
                let response = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject]
                print(response!)
                //Your code here                    
            } catch let error as NSError {
                print(error)
            }
        }

        task.resume()

    }

}

如果你有兴趣在SharedClass中使用这个函数

//My shared class
import UIKit
class SharedClass: NSObject {

static let sharedInstance = SharedClass()

func postRequestFunction(apiName: String , parameters: String, onCompletion: @escaping (_ success: Bool, _ error: Error?, _ result: [String: Any]?)->()) {

    var URL =  "your URL here/index.php/***?"

    URL = URL.replacingOccurrences(of: "***", with: apiName)

    var request = URLRequest(url: URL(string: URL)!)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    print("shared URL : \(request)")
    request.httpBody = parameters.data(using: .utf8)

    var returnRes:[String:Any] = [:]
    let task = URLSession.shared.dataTask(with: request) { data, response, error in

        if let error = error {
            onCompletion(false, error, nil)
        } else {
            guard let data = data else {
                onCompletion(false, error, nil)
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
                do {
                   returnRes = try JSONSerialization.jsonObject(with: data, options: []) as! [String : Any]
                    onCompletion(true, nil, returnRes)

                } catch let error as NSError {
                   onCompletion(false, error, nil)
                }
            } else {
                onCompletion(false, error, nil)
            }
        }
    }
    task.resume()
}


private override init() {

}

最后像这样调用这个函数....

SharedClass.sharedInstance.postRequestFunction(apiName: "Your API name", parameters: parameters) { (success, error, result) in
    print(result!)
    if success {
        //Your code here
    } else {
        print(error?.localizedDescription ?? "")
    }
}

//这是一个对我有用的例子

//发送请求到服务器的Swift函数

func insertRecords()
{



    let usrID = txtID.text
    let checkin = lblInOut.text
    let comment = txtComment.text



    // The address of the web service
    let urlString = "http://your_url/checkInOut_post.php"

    // These are the keys that your are sending as part of the post request
    let keyValues = "id=\(usrID)&inout=\(checkin)&comment=\(comment)"




    // 1 - Create the session by getting the configuration and then
    //     creating the session

    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)


    // 2 - Create the URL Object

    if let url = NSURL(string: urlString){


        // 3 - Create the Request Object

        var request  = NSMutableURLRequest(URL: url)
        request.HTTPMethod = "POST"

        // set the key values
        request.HTTPBody = keyValues.dataUsingEncoding(NSUTF8StringEncoding);


        // 4 - execute the request

        let taskData = session.dataTaskWithRequest(request, completionHandler: {

            (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in

            println("\(data)")

            // 5 - Do something with the Data back

            if (data != nil) {

                // we got some data back
                println("\(data)")

                let result = NSString(data: data , encoding: NSUTF8StringEncoding)
                println("\(result)")

                if result == "OK" {

                    let a = UIAlertView(title: "OK", message: "Attendece has been recorded", delegate: nil, cancelButtonTitle: "OK")

                    println("\(result)")

                    dispatch_async(dispatch_get_main_queue()) {


                    a.show()


                    }


                } else {
                  // display error and do something else

                }


            } else

            {   // we got an error
                println("Error getting stores :\(error.localizedDescription)")

            }


        })

        taskData.resume()



    }


}

PHP代码来获取键值

$empID = $_POST['id'];

$inOut = $_POST['inout'];

$comment = $_POST['comment'];

你可以使用URL URLRequest URLSession或者NSURLConnection就像你在Objective-C中通常做的那样。注意,对于iOS 7.0及更高版本,URLSession是首选。

使用URLSession

初始化URL对象和URLSession中的URLSessionDataTask。然后使用resume()运行任务。

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

使用NSURLConnection

首先,初始化URL和URLRequest:

let url = URL(string: "http://www.stackoverflow.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST" 

然后,你可以异步加载请求:

NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {(response, data, error) in
    guard let data = data else { return }
    print(String(data: data, encoding: .utf8)!)
}

或者你可以初始化一个NSURLConnection:

let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)

只是要确保将委托设置为nil以外的东西,并使用委托方法处理接收到的响应和数据。

要了解更多细节,请查看NSURLConnectionDataDelegate协议的文档

在Xcode操场上测试

如果你想在Xcode游乐场上尝试这段代码,添加import PlaygroundSupport到你的游乐场,以及下面的调用:

PlaygroundPage.current.needsIndefiniteExecution = true

这将允许你在操场上使用异步代码。

另一个选择是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)
          }