Swift 3 – 发送同步http请求

我有以下代码:

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 } 

我需要能够调用这个,同时检查返回值,因为它是http状态码,它会告诉我,如果通话成功与否。

问题是因为它在dataTask中,我无法在这里访问响应状态码

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

因为直到Task.Resume()被调用并且任务是asynchronous的,任务才会启动,所以它永远不会工作。

有没有办法解决这个问题?

总有一种方法可以使用asynchronous模式。

要使该functionasynchronous添加完成块

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

并称之为

 completeLoadAction(urlString: "www.something.com") { code in print(code) } 

为了使它同步,并等待你可以使用信号如下

 struct Login { static func execute() -> Bool { let request = NSURLRequest.... var success = false let semaphore = DispatchSemaphore(value: 0) let task = URLSession.shared.dataTask(with: request, completionHandler: { _, response, error in if let error = error { print("Error while trying to re-authenticate the user: \(error)") } else if let response = response as? HTTPURLResponse, 300..<600 ~= response.statusCode { print("Error while trying to re-authenticate the user, statusCode: \(response.statusCode)") } else { success = true } semaphore.signal() }) task.resume() _ = semaphore.wait(timeout: DispatchTime.distantFuture) return success } } 

这在所有情况下都不起作用。 假设您正在实施共享扩展。 而你重写的isContentValid()方法返回一个布尔值(如果内容是有效的,则为true)…但为了testing内容是否有效,需要validation服务器是否正在运行(这是一个人为的例子)。 如果你build立一个asynchronoushttp调用完成块,你不能返回正确的布尔值; 唯一的方法就是做一个同步调用,根据返回值返回true / false。

发布信号模式的答案在这种情况下是正确的。