Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 3 - Send make synchronous http request

I have the following code:

func completeLoadAction(urlString:String) -> Int {
    let url = URL(string:urlString.trimmingCharacters(in: .whitespaces))
    let request = URLRequest(url: url!)
    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=\(error)")
            let ac = UIAlertController(title: "Unable to complete", message: "The load has been added to the completion queue. This will be processed once there is a connection.", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            self.present(ac, animated:  true)
            return
        }

    let httpStatus = response as? HTTPURLResponse
        var httpStatusCode:Int = (httpStatus?.statusCode)!

        let responseString = String(data: data, encoding: .utf8)
        print("responseString = \(responseString)")
        let ac = UIAlertController(title: "Completed Successfully", message: "The "+coldel+" has been completed successfully", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title:"Continue", style: .default, handler:  { action in self.performSegue(withIdentifier: "segueConfirmedLoad", sender: self) }))

        self.present(ac, animated: true)

    }
    task.resume()
    return httpStatusCode
}

I need to be able to call this and at the same time check the return value as it is the http status code, it will let me know if the call was successful or not.

Problem is because it's in a dataTask I can't access the responses status code here

var httpStatusCode:Int = (httpStatus?.statusCode)!

Because the task doesn't start until Task.Resume() is called and the task is asynchronous so it will never work.

Are there any ways around this?

like image 763
Alec. Avatar asked Nov 08 '16 16:11

Alec.


Video Answer


1 Answers

There is always a way to use the asynchronous pattern.

To make the function asynchronous add a completion block

func completeLoadAction(urlString:String, completion: (Int) -> ()) {
   let url = URL(string:urlString.trimmingCharacters(in: .whitespaces))
   let request = URLRequest(url: url!)
   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=\(error)")
         DispatchQueue.main.async {
            let ac = UIAlertController(title: "Unable to complete", message: "The load has been added to the completion queue. This will be processed once there is a connection.", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            self.present(ac, animated:  true)
         }
         completion(0) // or return an error code 
         return     
      }

      let httpStatus = response as? HTTPURLResponse
      var httpStatusCode:Int = (httpStatus?.statusCode)!

      let responseString = String(data: data, encoding: .utf8)
      print("responseString = \(responseString)")
      DispatchQueue.main.async {
         let ac = UIAlertController(title: "Completed Successfully", message: "The "+coldel+" has been completed successfully", preferredStyle: .alert)
         ac.addAction(UIAlertAction(title:"Continue", style: .default, handler:  { action in self.performSegue(withIdentifier: "segueConfirmedLoad", sender: self) }))
         self.present(ac, animated: true)
      }
      completion(httpStatusCode)
   }
   task.resume()

}

and call it thusly

completeLoadAction(urlString: "www.something.com") { code in
   print(code)
}
like image 54
vadian Avatar answered Oct 03 '22 15:10

vadian