如何在 Swift 中执行 GET 和 POST 请求?

How do I perform GET and POST requests in Swift?

我改编自 Ray Wenderlich 的 iOS 学徒教程第 4 部分。

此代码作为 GET 请求发送到我的 Strongloop API,具有简单的数据库模型,但是:

  1. 这行得通,但我不知道它为什么行得通,因为它没有调用我可以看到的实际发送请求的方法。

  2. 我看不出有什么办法可以将其变成 POST 请求。

我的问题是:如何执行 POST 请求?它是以完全不同的方式完成的吗?

如果您需要更多信息,请告诉我。

    class ViewController: UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func getFromDB() {
        let url = urlWithSearchText("")
        println("URL: '\(url)'")
        if let jsonString = performGetRequestWithURL(url) {
            println("Received JSON string '\(jsonString)'")
        }
    }


    func urlWithSearchText(searchText: String) -> NSURL {
        let escapedSearchText = searchText.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
        let urlString = String(format: "http://localhost:3000/api/Tests", escapedSearchText)
        let url = NSURL(string: urlString)
        return url!
    }    

    func performGetRequestWithURL(url: NSURL) -> String? {
        var error: NSError?
        if let resultString = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) {
            return resultString
        } else if let error = error {
            println("Download Error: \(error)")
        } else {
            println("Unknown Download Error")
        }
        return nil
    }

这是一张工作照片:

https://dl.dropboxusercontent.com/u/14464971/Images/Messages%20Image%281477993527%29.png

此方法调用 http 请求。

String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) 

因为Swift String没有这样的初始化签名

这个方法会写在项目的某处,如extension of String

会是这样的

extension String{
    init(contentsOfURL: NSURL, encoding: NSUTF8StringEncoding, inout error: NSError){
        // load data from url
        self = //parse data to string
    }
}

下面是两种POST方法。取决于你是想让它同步(其他一切都等到 post 方法完成)还是异步(POST 方法 运行s 在后台,其他方法 运行 并行) .

方法

// POST data to url
func postDataAsynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ()) {
    var URL: NSURL = NSURL(string: url)!
    var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
    request.HTTPMethod = "POST";
    request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){

        response, data, error in

        var output: String!

        if data != nil {
            output = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
        }

        completionHandler(responseString: output, error: error)
    }
}

// Obtain the data
func postDataSynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ())
{
    let URL: NSURL = NSURL(string: url)!
    var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
    request.HTTPMethod = "POST"
    request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

    var response: NSURLResponse?
    var error: NSError?

    // Send data
    let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)

    var output: String! // Default to nil

    if data != nil{
        output =  NSString(data: data!, encoding: NSUTF8StringEncoding) as! String
    }

    completionHandler(responseString: output, error: error)

}

使用它们

然后您可以像这样调用(使用)它们:

postDataSynchronous(url, bodyData: bodyData) {
    responseString, error in

        if error != nil {
            println("Error during post: \(error)")
            return
        }
        else{
            //Success
            println(responseString)
            userType = responseString // Set usertype based on server response
        }        
    }

SWIFT 2.0

func postData(url: String, params: Dictionary<String, String>, completionHandler: (data: NSData?, response: NSURLResponse?, error: NSError?) -> ()) {

    // Indicate download
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    let url = NSURL(string: url)!
    //        print("URL: \(url)")
    let request = NSMutableURLRequest(URL: url)
    let session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    // Verify downloading data is allowed
    do {
        request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
    } catch let error as NSError {
        print("Error in request post: \(error)")
        request.HTTPBody = nil
    } catch {
        print("Catch all error: \(error)")
    }

    // Post the data
    let task = session.dataTaskWithRequest(request) { data, response, error in
        completionHandler(data: data, response: response, error: error)

        // Stop download indication
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false // Stop download indication

    }

    task.resume()

}

String(contentsOfUrl:encoding:error) 初始化程序在后台发出 GET 请求,returns 内容作为具有指定编码的字符串。

发出请求的一种方法是创建一个 NSURLConnection 并使用 NSMutablrURLRequest 设置 HTTP 方法 post。使用 NSMutableURLRequest,您可以创建一个 NSURLConnection 并使用委托立即启动它,或者您可以调用 NSURLConnection.sendSynchronousRequest 或 NSURLConnection.sendAsynchronousRequest 来发送请求。

Swift 3 岁及以上

GET

 func getRequest() {
    
    // request url
    let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! // change the url
    
    // create URLSession with default configuration
    let session = URLSession.shared
    
    // create dataTask using the session object to send data to the server
    let task = session.dataTask(with: url) { data, response, error in
        
        if let error = error {
            print("GET Request Error: \(error.localizedDescription)")
            return
        }
        
        // ensure there is valid response code returned from this HTTP response
        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
                  print("Invalid Response received from the server")
                  return
              }
        
        // ensure there is data returned
        guard let responseData = data else {
            print("nil Data received from the server")
            return
        }
        
        do {
            // serialise the data object into Dictionary [String : Any]
            if let jsonResponse = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? [String: Any] {
                print(jsonResponse)
            } else {
                print("data maybe corrupted or in wrong format")
                throw URLError(.badServerResponse)
            }
        } catch let error {
            print("JSON Parsing Error: \(error.localizedDescription)")
        }
    }
    // resume the task
    task.resume()
}

POST

func postRequest() {
    
    // declare the parameter as a dictionary that contains string as key and value combination. considering inputs are valid
    
    let parameters: [String: Any] = ["name": "abc", "password": "password@123"]
    
    // create the url with URL
    let url = URL(string: "http://myServerName.com/api")! //change the url
    
    // create the session object
    let session = URLSession.shared
    
    // now create the URLRequest object using the url object
    var request = URLRequest(url: url)
    request.httpMethod = "POST" //set http method as POST
    
    // add headers for the request
    request.addValue("application/json", forHTTPHeaderField: "Content-Type") // change as per server requirements
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    
    do {
        // convert parameters to Data and assign dictionary to httpBody of request
        request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
    } catch let error {
        print(error.localizedDescription)
        return
    }
    
    // create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request) { data, response, error in
        
        if let error = error {
            print("Post Request Error: \(error.localizedDescription)")
            return
        }
        
        // ensure there is valid response code returned from this HTTP response
        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode)
        else {
            print("Invalid Response received from the server")
            return
        }
        
        // ensure there is data returned
        guard let responseData = data else {
            print("nil Data received from the server")
            return
        }
        
        do {
            // create json object from data or use JSONDecoder to convert to Model stuct
            if let jsonResponse = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? [String: Any] {
                print(jsonResponse)
                // handle json response
            } else {
                print("data maybe corrupted or in wrong format")
                throw URLError(.badServerResponse)
            }
        } catch let error {
            print(error.localizedDescription)
        }
    }
    task.resume()
}
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { return }

    let session = URLSession.shared
    session.dataTask(with: url) { (data, response, error) in
        if let response = response {
            print(response)
        }

        if let data = data {
            print(data)
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: [])
                print(json)
            } catch {
                print(error)
            }

        }
    }.resume()
}

这是一个get方法。

let parameters = ["username": "@Bipin_kumar", "tweet": "HelloWorld"]

guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else { return }
request.httpBody = httpBody

let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
    if let response = response {
        print(response)
    }

    if let data = data {
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: [])
            print(json)
        } catch {
            print(error)
        }
    }

}.resume()

这是一个post方法。

GET 请求

 func getRequest(with url: URL, callback: @escaping (Any?) -> Swift.Void) -> Void {

    let defaultConfigObject = URLSessionConfiguration.default
    defaultConfigObject.timeoutIntervalForRequest = 30.0
    defaultConfigObject.timeoutIntervalForResource = 60.0

    let session = URLSession.init(configuration: defaultConfigObject, delegate: nil, delegateQueue: nil)

    var urlRequest = URLRequest(url: url as URL)
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")

    urlRequest.httpMethod = "GET"
    session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in

        guard    let httpResponse: HTTPURLResponse = response as? HTTPURLResponse
            else {
                print("Error: did not receive data")
                return
              }

        var response : (Any)? = nil

        if httpResponse.statusCode == 200 {
            print(httpResponse)

            guard let responseData = data else {
                print("Error: did not receive data")
                return
            }

            do {
                let responseData = try JSONSerialization.jsonObject(with: responseData, options: [JSONSerialization.ReadingOptions.allowFragments])

                  response = responseData
                 callback(response)
            }
            catch _ as NSError {

                let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                callback(responseString)
                return
            }
        }
        else {
            print(httpResponse)

            guard error == nil else {
                print("error calling GET on /todos/1")
                print(error ?? "error")
                callback(response!)
                return
            }

        }
    }).resume()
}

POST 请求

//MARK: post request
func postRequest(with url:URL, postBody:String, callback: @escaping (Any?) -> Void) -> Void {

    let defaultConfigObject = URLSessionConfiguration.default
    defaultConfigObject.timeoutIntervalForRequest = 30.0
    defaultConfigObject.timeoutIntervalForResource = 60.0

    let session = URLSession.init(configuration: defaultConfigObject, delegate: nil, delegateQueue: nil)

    let params: String! = postBody

    var urlRequest = URLRequest(url: url as URL)
    urlRequest.httpMethod = "POST"

    let data = params.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
    urlRequest.httpBody = data

    session.dataTask(with: urlRequest, completionHandler: { (data, urlResponse, error) in


        guard let httpResponse:HTTPURLResponse = urlResponse as? HTTPURLResponse
            else{
                print("did not get any data")
                return
            }
        var response : (Any)? = nil

        if httpResponse.statusCode == 200 {

            guard let responseData = data else {
                print("Error: did not receive data")
                return
            }

            do {
                guard let responseData = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
                    print("error trying to convert data to JSON")
                    return
                }

                response = responseData
                callback(response)
            } catch _ as NSError {

                let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                callback(responseString)
                return
            }
        }

        else {
        guard error == nil else {
            print("error calling GET on /todos/1")
            print(error ?? "error")
            callback(nil)
            return
        }
    }
    }).resume()
}

始终尝试检查 HTTPURLResponse 代码