Krish
Krish

Reputation: 4232

How to make NSURLSession POST request in Swift

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

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

Upvotes: 36

Views: 65392

Answers (9)

deepak bawa
deepak bawa

Reputation: 1

    import Foundation
    import UIKit
    class ViewModel:NSObject {
        func hitPostApi(username: String, password: String, completion: @escaping (Bool) -> Void) {
                let url = "https://dummyjson.com/auth/login"
                guard let serviceUrl = URL(string: url) else { return }
                
                let parameters: [String: Any] = [
                    "username": username,
                    "password": password
                ]
                
                var request = URLRequest(url: serviceUrl)
                request.httpMethod = "POST"
                request.setValue("application/json", forHTTPHeaderField: "Content-Type")
                
                guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
                    return
                }
                request.httpBody = httpBody
                request.timeoutInterval = 20
                
                let session = URLSession.shared
                session.dataTask(with: request) { (data, response, error) in
                    if let error = error {
                        print("Error: \(error.localizedDescription)")
                        completion(false)
                        return
                    }
                    
                    guard let data = data else {
                        completion(false)
                        return
                    }
                    
                    do {
                        let decoder = JSONDecoder()
                        if let loginResponse = try? decoder.decode(LoginproductModel.self, from: data) {
                            UserDefaults.standard.setValue(loginResponse.accessToken, forKey: "accessToken")
                            print("Login Successful")
                            print("Data",data)
                            print("Token", loginResponse.accessToken)
                            completion(true)  // Notify success
                        } else {
                            print("Failed to decode login response")
                            completion(false)
                        }
                    }
                }.resume()
            }
        
        func changeApiKey(completionHandler: @escaping(AfterLogin) -> Void) {
            if let url = URL(string: "https://dummyjson.com/auth/me") {
                
                var request = URLRequest(url: url)
                request.httpMethod = "GET"
                request.setValue("text/plain",forHTTPHeaderField: "Accept")
    //            request.addValue("sk_d3KmPtjEtdGTjChLB0ylraAb/AWgfyR9MOxFXwgEWSZsnpoIXFVDfm1Snoak0ufRe0w=", forHTTPHeaderField: "secret_key")
    //            request.addValue("pk_Bvk6rVC7WxbRW2O3sy4xwCEiM+n8jdT55BQv4BA0zG4IawzpbDhTVzSvj43DcvU7cM0x", forHTTPHeaderField: "publish_key")
               // request.addValue("Bearer \(String(describing: UserDefaults.standard.string(forKey: "acessToken")))", forHTTPHeaderField: "Authorization")
                var token = String()
                token = UserDefaults.standard.string(forKey: "accessToken") ?? ""
                request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
                let task = URLSession.shared.dataTask(with: request) { data, response, error in
                    guard error == nil else {
                        print(error!)
                        return
                    }
                    guard let jsonData = data else { return }
                    do {
                        let decoder = JSONDecoder()
                        let productsResponse = try decoder.decode(AfterLogin.self, from: jsonData)
                        let productDetails = productsResponse
                        DispatchQueue.main.async {
                            //self.tblData = productDetails.body?.nutritionistsList
                          //  tbale.reloadData()
                        }
                        
    
                        completionHandler(productDetails)
                    }catch {
                        print(error.localizedDescription)
                    }
    
                }
                task.resume()
            }
        }
        }
   // usage
    @IBAction func btnLogin(_ sender: UIButton) {
        vIewModel.hitPostApi(username: textUername.text ?? "", password: textPassword.text ?? "") { success in
                   DispatchQueue.main.async {
                       if success {
                           let vc = self.storyboard?.instantiateViewController(withIdentifier: "HomeView") as! HomeView
                           self.navigationController?.pushViewController(vc, animated: true)
                       } else {
                           print("Login failed")
                       }
                   }
               }
    }
    var viewModel = ViewModel()
var model:AfterLogin?

override func viewDidLoad() {
    super.viewDidLoad()

    viewModel.changeApiKey {
        [weak self] data in
        DispatchQueue.main.sync {
            self?.model = data
            self?.lblName.text = "\(self?.model?.firstName ?? "") \(self?.model?.maidenName ?? "") \((self?.model?.lastName ?? ""))"
            self?.lblAge.text = "\(self?.model?.age ?? 0)"
            self?.lblGender.text = "\(self?.model?.gender ?? "")"
            self?.lblemail.text = "\(self?.model?.email ?? "")"
            self?.lblPhone.text = "\(self?.model?.phone ?? "")"
            self?.lblbloodgroup.text = "\(self?.model?.bloodGroup ?? "")"
            self?.lblHeight.text = "\(self?.model?.height ?? 0.0)"
            self?.lblWeigt.text = "\(self?.model?.weight ?? 0.0)"
            self?.lblEyeColor.text = "\(self?.model?.eyeColor ?? "")"
            self?.lblHair.text = "\(self?.model?.hair?.color ?? "")"
            self?.lblhairType.text = "\(self?.model?.hair?.type ?? "")"
            self?.lblNAdrees.text = "\(self?.model?.address?.city ?? "")\(self?.model?.address?.state ?? "") \(self?.model?.address?.country ?? "")"
            self?.lbluniversity.text = "\(self?.model?.university ?? "")"
            self?.lblComdpart.text = "\(self?.model?.company?.department ?? "")"
            
            guard let url = URL(string: "\(self?.model?.image ?? "")") else { return }

            UIImage.loadFrom(url: url) { image in
                self?.img.image = image
            }
        }
    }
    
    
}

Upvotes: -1

Darshak Suhagiya
Darshak Suhagiya

Reputation: 1

in API Calling if you want to pass headers, params and body. also parse response data in your custom model

    let Url = String(format: "https://reqres.in/api/users")
    guard let serviceUrl = URL(string: Url) else { return }

    let parameters = ["page" : "2"]
    let body = ["email": "[email protected]", "password": "pistol"]
    let headers = ["token": "123425657"]

    var request = URLRequest(url: serviceUrl)
    request.httpMethod = "GET"

    var components = URLComponents(url: serviceUrl, resolvingAgainstBaseURL: false)
        components?.queryItems = parameters.map { URLQueryItem(name: $0.key, value: $0.value) }
        request.url = components?.url

    do {
         let jsonData = try JSONSerialization.data(withJSONObject: body, options: [])
         request.httpBody = jsonData
     } catch {
         print("Failed to serialize body data:", error)
         return
     }

    request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
    for (key, value) in headers {
        request.setValue(value, forHTTPHeaderField: key)
    }

    let session = URLSession.shared
    session.dataTask(with: request) { (data, response, error) in
        if let response = response {
            print(response)
        }
        if let data = data {
            do {
                let decoder = JSONDecoder()
                let user = try decoder.decode(User.self, from: data)
                print("User:", user)
            } catch {
                print("Failed to decode response data:", error)
            }
        }
    }.resume()

Upvotes: 0

Abhishek Jain
Abhishek Jain

Reputation: 4737

Swift 4 post example with json payload-

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

Upvotes: 84

Nirbhay Singh
Nirbhay Singh

Reputation: 1298

Try this: (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()
}

Upvotes: 0

abdullahselek
abdullahselek

Reputation: 8463

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

Endpoint to create urls

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

User object model for request body

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

UserResponse model for http response comes from 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"
    }
}

APIClient make http requests for our api

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

}

Upvotes: 10

Dheeraj Gupta
Dheeraj Gupta

Reputation: 380

Try to run this function and print the response, it is in 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.

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

Upvotes: 9

Sayan Banerjee
Sayan Banerjee

Reputation: 11

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

Upvotes: 1

Lineesh K Mohan
Lineesh K Mohan

Reputation: 1712

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

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)

Upvotes: 2

Avinash Mishra
Avinash Mishra

Reputation: 797

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

Upvotes: 4

Related Questions