ios 如何在 Swift 中发出 NSURLSession POST 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41997641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 11:07:33  来源:igfitidea点击:

How to make NSURLSession POST request in Swift

iosswiftnsurlsession

提问by Krish

Hi I am very beginner for Swift and I am trying to make NSURLSession "Post" request sending some parameter like my below code

嗨,我是 Swift 的初学者,我正在尝试使 NSURLSession“发布”请求发送一些参数,如下面的代码

According to my below code response not coming from server can some one help me please

根据我下面的代码响应不是来自服务器,有人可以帮助我吗

BackGroundClass:-

背景类:-

 import UIKit

protocol sampleProtocal{

    func getResponse(result:NSDictionary)
    func getErrorResponse(error:NSString)
}

class BackGroundClass: NSObject {

    var delegate:sampleProtocal?

    func callPostService(url:String,parameters:NSDictionary){


        print("url is===>\(url)")

        let request = NSMutableURLRequest(URL: NSURL(string:url)!)

        let session = NSURLSession.sharedSession()
        request.HTTPMethod = "POST"

        //Note : Add the corresponding "Content-Type" and "Accept" header. In this example I had used the application/json.
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])

        let task = session.dataTaskWithRequest(request) { data, response, error in
            guard data != nil else {
                print("no data found: \(error)")
                return
            }

            do {
                if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                    print("Response: \(json)")
                    self.mainResponse(json)
                } else {
                    let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)// No error thrown, but not NSDictionary
                    print("Error could not parse JSON: \(jsonStr)")
                    self.eroorResponse(jsonStr!)
                }
            } catch let parseError {
                print(parseError)// Log the error thrown by `JSONObjectWithData`
                let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
                print("Error could not parse JSON: '\(jsonStr)'")
                self.eroorResponse(jsonStr!)
            }
        }

        task.resume()
    }

    func mainResponse(result:NSDictionary){
        delegate?.getResponse(result)
    }

    func eroorResponse(result:NSString){
        delegate?.getErrorResponse(result)
    }
}

ViewController:-

视图控制器:-

import UIKit

class ViewController: UIViewController,sampleProtocal {

    override func viewDidLoad() {
        super.viewDidLoad()

        let delegate = BackGroundClass();
        delegate.self;

        let params = ["scancode":"KK03799-008", "UserName":"admin"] as Dictionary<String, String>

        let backGround=BackGroundClass();
        backGround.callPostService("url", parameters: params)
    }

    func getResponse(result: NSDictionary) {
        print("Final response is\(result)");
    }

    func getErrorResponse(error: NSString) {
        print("Final Eroor code is\(error)")
    }
}

回答by Abhishek Jain

Swift 4post example-

Swift 4发布示例-

func postAction(_ sender: Any) {
        let Url = String(format: "your url")
        guard let serviceUrl = URL(string: Url) else { return }
        let parameterDictionary = ["username" : "Test", "password" : "123456"]
        var request = URLRequest(url: serviceUrl)
        request.httpMethod = "POST"
        request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
        guard let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, 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()
    }

回答by Dheeraj Gupta

Try to run this function and print the response, it is in Swift 4.0.

尝试运行此函数并打印响应,它在 Swift 4.0 中。

Here, I have prepared codable structure:

在这里,我准备了可编码的结构:

struct LoginData: Codable {
    var code: Int?
    var message: String?
    var status: String?
    var token: String?
    var data: DataSet?
}
struct DataSet: Codable {
    var email : String?
    var contactNo : String?
    var firstName : String?
    var lastName: String?
    var dob : String?
    var gender : String?
    var address: String?
    var city : String?
    var state : String?
    var country : String?
    var zip : String?
    var username: String?
}

If you get your response printed correctly then pass it to your viewController.

如果您的响应打印正确,则将其传递给您的 viewController。

func loginWS(parameters:[String:String], completionHandler: @escaping (Any?) -> Swift.Void) {

    guard let gitUrl = URL(string: BASE_URL+ACTION_URL) else { return }
    print(gitUrl)

    let request = NSMutableURLRequest(url: gitUrl)
    //  uncomment this and add auth token, if your project needs.
    //  let config = URLSessionConfiguration.default
    //  let authString = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMywiUGFzc3dvcmQiOiIkMmEkMTAkYVhpVm9wU3JSLjBPYmdMMUk2RU5zdU9LQzlFR0ZqNzEzay5ta1pDcENpMTI3MG1VLzR3SUsiLCJpYXQiOjE1MTczOTc5MjV9.JaSh3FvpAxFxbq8z_aZ_4OhrWO-ytBQNu6A-Fw4pZBY"
    //  config.httpAdditionalHeaders = ["Authorization" : authString]

    let session = URLSession.shared
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.httpBody = try! JSONSerialization.data(withJSONObject: parameters, options: [])

    let task = session.dataTask(with: request as URLRequest) { data, response, error in

        guard let data = data else { return }
        do {
        //  let decoder = JSONDecoder()
        //  here replace LoginData with your codable structure.
            let gitData = try JSONDecoder().decode(LoginData.self, from: data)
            print("response data:", gitData) 
            completionHandler(gitData)
        } catch let err {
            print("Err", err)
        }
        }.resume()
}

回答by abdullahselek

Here is a sample complete solution compatible with Swift 4and Swift 5.

这是一个与Swift 4Swift 5兼容的完整解决方案示例。

Endpointto create urls

Endpoint创建网址

struct Endpoint {
    let path: String
    let queryItems: [URLQueryItem]?
}

extension Endpoint {
    var url: URL? {
        var components = URLComponents()
        components.scheme = "https"
        components.host = "YOUR_HOST"
        components.path = path
        components.queryItems = queryItems
        return components.url
    }
}

Userobject model for request body

User请求体的对象模型

struct User: Encodable {
    let name: String
    let surname: String
    let age: Int

    // this is to customise init 
    init(name: String,
         surname: String,
         age: Int) {
        self.name = name
        self.surname = surname
        self.age = age
    }

    enum CodingKeys: String, CodingKey {
        case name, surname, age
    }
}

UserResponsemodel for http response comes from API

UserResponsehttp 响应模型来自 API

struct UserResponse: Decodable {
    let message: String
    let userId: String?

    enum CodingKeys: String, CodingKey {
        case message, userId = "user_id" // API returns userId as "user_id"
    }
}

APIClientmake http requests for our api

APIClient为我们的 api 发出 http 请求

protocol APIClientProtocol: Any {
    func sendUser(_ user: User, completionBlock: @escaping (_ userResponse: UserResponse?, _ error: APIClient.Error?) -> Void)
}

class APIClient: APIClientProtocol {

    fileprivate let defaultSession: URLSession = {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 10.0
        configuration.timeoutIntervalForResource = 10.0
        return URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
    }()

    public init() { }

    public func uploadUser(_ user: User, completionBlock: @escaping (UserResponse?, APIClient.Error?) -> Void) {
        guard let url = Endpoint(path: "/user/upload", queryItems: nil).url else {
            completionBlock(nil, .brokenURL)
            return
        }
        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = "POST"
        urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
        urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
        do {
            let jsonData = try JSONEncoder().encode(user)
            urlRequest.httpBody = jsonData
        } catch {
            completionBlock(nil, .serialization(error.localizedDescription))
            return
        }
        let task = defaultSession.dataTask(with: urlRequest) { data, urlResponse, error in
            if let error = error {
                completionBlock(nil, .http(error.localizedDescription))
                return
            }
            guard let httpResponse = urlResponse as? HTTPURLResponse else {
                return
            }
            if httpResponse.statusCode == 200 {
                guard let data = data else {
                    return
                }
                do {
                    let userResponse = try JSONDecoder().decode(UserResponse.self, from: data)
                    completionBlock(userResponse, nil)
                } catch let error {
                    completionBlock(nil, .serialization(error.localizedDescription))
                }
            } else {
                completionBlock(nil, .http("Status failed!"))
            }
        }
        task.resume()
    }

}

extension APIClient {

    enum Error: Swift.Error, Equatable {
        case brokenURL
        case serialization(String)
        case http(String)
    }

}

回答by Avinash Mishra

Post Class

岗位类

func post(params : Dictionary<String, String>, url : String) {
    var request = NSMutableURLRequest(URL: NSURL(string: url))
    var session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"

    var err: NSError?
    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        println("Response: \(response)")
        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
        println("Body: \(strData)")
        var err: NSError?
        var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary

        // Did the JSONObjectWithData constructor return an error? If so, log the error to the console
        if(err != nil) {
            println(err!.localizedDescription)
            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
            println("Error could not parse JSON: '\(jsonStr)'")
        }
        else {
            // The JSONObjectWithData constructor didn't return an error. But, we should still
            // check and make sure that json has a value using optional binding.
            if let parseJSON = json {
                // Okay, the parsedJSON is here, let's get the value for 'success' out of it
                var success = parseJSON["success"] as? Int
                println("Succes: \(success)")
            }
            else {
                // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                println("Error could not parse JSON: \(jsonStr)")
            }
        }
    })

    task.resume()
}

call This Method Like This

像这样调用这个方法

 self.post(["username":"jameson", "password":"password"], url: "http://localhost:4567/login")

Hope It Helps :)

希望能帮助到你 :)

回答by Lineesh K Mohan

Http body is missing. Example - setting string paramets as body

缺少 Http 正文。示例 - 将字符串参数设置为正文

let paramString = String(format:"param1=%@&param2=%@",param1,param2)
request.httpBody = paramString.data(using: String.Encoding.utf8)

here just try

在这里试试

request.httpBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)

回答by Sayan Banerjee

func getData(searchString:String,completion:@escaping(Any)->Void){
    let url = "https://itunes.apple.com/search?term="+searchString
    URLSession.shared.dataTask(with: URL.init(string: url)!){(data,response,err) in
        if let responsedata = data{
            DispatchQueue.main.async {
                completion(responsedata)
            }
        }
    }.resume()
}

回答by Nirbhay Singh

Try this: (Swift 4.2)

试试这个:(Swift 4.2)

public func submitDelivery(delivery:DeliveryModal,responseCode:String,completion:@escaping SubmitCompletionBlock){

    let urlString = BaseURL.getURL(urlType: .submit(responseCode))
    guard let url = URL(string: urlString) else { return }
    var request : URLRequest = URLRequest(url: url)
    request.httpMethod = HttpMethod.post.rawValue
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted

    do {
        let jsonData = try encoder.encode(delivery)
        request.httpBody = jsonData

    } catch {
        print(error.localizedDescription)
        completion(nil,nil,NSError.init())
    }

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

        guard let data = data else {
            completion(nil,response,NSError.init())
            return
        }
        do {
            let data = try JSONDecoder().decode(DeliverySubmitResponseModal.self, from: data)
            DispatchQueue.main.async {
                completion(data,response,error)
            }
        } catch let error {
            debugPrint(error.localizedDescription)
        }

    }
    dataTask.resume()
}