Search code examples
iosswifthttp-methodurlrequest

calling a web service with httpMethod (POST) in swift 4.1


Let me describe view controller (page design) first. I have added one button and one label. And a function is created by me for the button. Here is the ViewController.swift file:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var btnHitWebService: UIButton!
    @IBOutlet weak var lblResult: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func btnHitWebServiceClick(_ sender: Any) {
        if (getTokenWithPostMethod() == true)
        {
            lblResult.text = "yes, we get token: " + g_token
        }
        else
        {
            lblResult.text = "there is an error, please try again later"
        }
    }

    func getTokenWithPostMethod() -> Bool{

        var funcResult = false

        var request = URLRequest(url: URL(string: "https://apiABCDEFG.com/token")!)
        request.httpMethod = "POST"
        let postString = "grant_type=password&username=ABCDEF&password=ABCDEF"
        request.httpBody = postString.data(using: .utf8)
        request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request)
        {
            data, response, error in
            guard let data = data, error == nil else
            {
                // check for fundamental networking error
                print("error=\(String(describing: error))")
                return
            }

            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
            {
                if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject]
                {
                    g_token = (jsonObject["access_token"] as? String)!
                    print(g_token)
                    g_token_type = (jsonObject["token_type"] as? String)!
                    print("\n")
                    print(g_token_type)
                    funcResult = true ;
                }
            }
            catch let error as NSError
            {
                print(error)
            }
        }

        task.resume()
        return funcResult
    }
}

Here is my problem: When I click button, it gives me a token in output screen in Xcode (print) but getTokenWithPostMethod() method returns false. Why does it return false? During the debug process, it jumps from let task = to task.resume(). Thanks! (by the way I can't share correct link, username and password. I hope these 3 are not necessary to fix this problem)


Solution

  • You are making an API call. It takes time to return the value. Here return statement will not wait for response. you should use either closure or delegate. You can try the given code:

    func getTokenWithPostMethod(handler: @escaping (_ funcResult: Bool) -> Void){
    
        var request = URLRequest(url: URL(string: "https://apiABCDEFG.com/token")!)
        request.httpMethod = "POST"
        let postString = "grant_type=password&username=ABCDEF&password=ABCDEF"
        request.httpBody = postString.data(using: .utf8)
        request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
    
        let task = URLSession.shared.dataTask(with: request)
        {
            data, response, error in
            var funcResult = false
    
            if error == nil, let data = data {
                do
                {
                    if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject]
                    {
                        g_token = (jsonObject["access_token"] as? String)!
                        print(g_token)
                        g_token_type = (jsonObject["token_type"] as? String)!
                        print("\n")
                        print(g_token_type)
                        funcResult = true
                    }
                }
                catch let error as NSError
                {
                    print(error)
                }
            }
            // edited
            DispatchQueue.main.async {
                handler(funcResult)
            }
        }
        task.resume()
    }
    

    This will return after the response comes. Replace the calling of that method with :

    @IBAction func btnHitWebServiceClick(_ sender: Any) {
    
        getTokenWithPostMethod { (flag) in
            if flag {
                lblResult.text = "yes, we get token: " + g_token
            } else {
                lblResult.text = "there is an error, please try again later"
            }
        }
    }
    

    For more details please visit