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

qv7cva1a  于 2023-05-05  发布在  Swift
关注(0)|答案(8)|浏览(112)

我改编自Ray Wenderlich的iOS Apprentice教程第4部分。
这段代码作为一个GET请求发送到我的Strongloop API,使用一个简单的数据库模型,但是:
1.这是可行的,但我不知道为什么可行,因为它没有调用任何方法来实际发送请求。
1.我看不出有什么办法可以把它变成一个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

nukf8bse

nukf8bse1#

Swift 3及以上版本
获取

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

发布

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

xzlaal3s2#

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

方法

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

}
jmo0nnb3

jmo0nnb33#

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方法。

wkftcu5l

wkftcu5l4#

此方法调用http请求。

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

因为Swift String没有这样的init签名。
此方法将在项目中的某个位置编写为extension of String
应该是这样的

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

5sxhfpxr5#

String(contentsOfUrl:encoding:error)初始化器在后台发出一个GET请求,并以指定编码的字符串形式返回内容。
发出请求的一种方法是创建一个NSURLConnection并使用NSMutablrURLRequest设置HTTP方法。使用NSMutableURLRequest,您可以创建一个NSURLConnection并使用委托立即启动它,或者您可以调用NSURLConnection.sendSynchronousRequest或NSURLConnection.sendAsynchronousRequest来发送请求。

xesrikrc

xesrikrc6#

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方法。

hs1rzwqc

hs1rzwqc7#

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

发布请求

//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代码

mjqavswn

mjqavswn8#

步骤:#1:APIRequest.swift

//
//  APIRequest.swift
//  Demo
//
//  Created by MANNAM on 14/02/23.
//

import Foundation

enum HTTPMethod: String {
    case GET
    case POST
    case PUT
    case DELETE
}

struct APIRequest {
    let url: URL
    let method: HTTPMethod
    let headers: [String: String]?
    let queryParams: [String: Any]?
    let body: Data?
}

步骤:#2:URLSessionApiClient.swift

//
//  URLSessionApiClient.swift
//  Demo
//
//  Created by MANNAM on 14/02/23.
//

import Foundation

final class URLSessionApiClient: NetworkClient {
    
    private let configuration: URLSessionConfiguration
    private let session: URLSession
    
    init() {
        self.configuration = URLSessionConfiguration.default
        self.configuration.timeoutIntervalForRequest = 30.0
        self.configuration.httpAdditionalHeaders = ["Content-Type": "application/json"]
        
        self.session = URLSession(configuration: self.configuration)
    }
    
    private func prepareURL(_ api: APIRequest) -> URL? {
        var urlComponents = URLComponents(string: api.url.absoluteString)
        let queryItems = api.queryParams?.map({ (key, value) in
            return URLQueryItem(name: key, value: String(describing: value) )
        })
        urlComponents?.queryItems = queryItems
        return urlComponents?.url
    }
    
    func dataTask<T: Codable>(_ api: APIRequest, onCompletion: @escaping (_ result: Result<T, Error>) -> Void) {
        
        guard let url = prepareURL(api) else {
            return onCompletion(.failure(AppError.invalidURL))
        }
        
        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = api.method.rawValue
        urlRequest.allHTTPHeaderFields = api.headers
        urlRequest.httpBody = api.body
        
        self.session.dataTask(with: urlRequest) { data, response, error in
            
            // onFailure
            if let err = error {
                onCompletion(.failure(err))
                return
            }
            
            // Validation
            guard (200...299).contains((response as? HTTPURLResponse)?.statusCode ?? 0) else {
                onCompletion(.failure(AppError.httpFailure))
                return
            }
            
            // onSuccess
            if let data = data {
                // Transform Data to Codable Type
                if let userModel = try? JSONDecoder().decode(T.self, from: data) {
                    onCompletion(.success(userModel))
                } else {
                    onCompletion(.failure(AppError.decodingError))
                }
            } else {
                onCompletion(.failure(AppError.noHttpBody))
            }
        }.resume()
    }
}

步骤:#3:AppError.swift

//
//  AppError.swift
//  Demo
//
//  Created by MANNAM on 14/02/23.
//

import Foundation

enum AppError: Error {
    case invalidURL
    case noHttpBody
    case httpFailure
    case decodingError
    case error(Error)
    case custom(String)
}

步骤:#4:NetworkClient.swift

//
//  NetworkClient.swift
//  Demo
//
//  Created by MANNAM on 14/02/23.
//

import Foundation

protocol NetworkClient {
    func dataTask<T: Codable>(_ api: APIRequest,
                              onCompletion: @escaping (_ result: Result<T, Error>) -> Void)
}

步骤:#5:ViewController.Swift

var client: NetworkClient = URLSessionApiClient()
 
 func getRequest() {
     let postsAPI = URL(string: "https://url/posts")!
     let apiRequest = APIRequest(url: postsAPI, method: .GET, headers: nil, queryParams: nil, body: nil)
     
     client.dataTask(apiRequest) { (_ result: Result<PostModel, Error>) in
         switch result {
         case .failure(let error):
             print(error)
         case .success(let data):
             print("Data: \(data)")
         }
     }
 }
 
 func postRequest() {
     let newPost = PostModel(userId: 1234, id: 1234, title: "My Title", body: "This is Body")
     let newPostData = try? JSONEncoder().encode(newPost)
     
     let postsAPI = URL(string: "https://url/posts")!
     let apiRequest = APIRequest(url: postsAPI, method: .POST, headers: ["Content-Type":"application/json"], queryParams: nil, body: newPostData)
     client.dataTask(apiRequest) { (_ result: Result<PostModel, Error>) in
         switch result {
         case .failure(let error):
             print(error)
         case .success(let data):
             print("Data: \(data)")
         }
     }
 }

相关问题