我可以以某种方式通过NSURLSession在Swift中执行同步HTTP请求

我可以以某种方式在Swift中通过NSURLSession执行同步HTTP请求吗?

我可以通过以下代码做一个asynchronous请求:

 if let url = NSURL(string: "https://2ch.hk/b/threads.json") { let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in var jsonError: NSError? let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject] if jsonError != nil { return } // ... } task.resume() } 

但是同步请求呢?

提前致谢。

你可以使用这个NSURLSession扩展来添加一个同步方法:

 extension NSURLSession { func synchronousDataTaskWithURL(url: NSURL) -> (NSData?, NSURLResponse?, NSError?) { var data: NSData?, response: NSURLResponse?, error: NSError? let semaphore = dispatch_semaphore_create(0) dataTaskWithURL(url) { data = $0; response = $1; error = $2 dispatch_semaphore_signal(semaphore) }.resume() dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) return (data, response, error) } } 

Swift 3的更新:

 extension URLSession { func synchronousDataTask(with url: URL) -> (Data?, URLResponse?, Error?) { var data: Data? var response: URLResponse? var error: Error? let semaphore = DispatchSemaphore(value: 0) let dataTask = self.dataTask(with: url) { data = $0 response = $1 error = $2 semaphore.signal() } dataTask.resume() _ = semaphore.wait(timeout: .distantFuture) return (data, response, error) } } 

苹果线程讨论相同的问题。

 + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(__autoreleasing NSURLResponse **)responsePtr error:(__autoreleasing NSError **)errorPtr { dispatch_semaphore_t sem; __block NSData * result; result = nil; sem = dispatch_semaphore_create(0); [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (errorPtr != NULL) { *errorPtr = error; } if (responsePtr != NULL) { *responsePtr = response; } if (error == nil) { result = data; } dispatch_semaphore_signal(sem); }] resume]; dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); return result; } 

通过Quinn“爱斯基摩人!” 苹果开发者关系,开发者技术支持,核心操作系统/硬件

更新了其中一个使用URLRequest的答案,所以我们可以使用PUT等。

 extension URLSession { func synchronousDataTask(urlrequest: URLRequest) -> (Data?, URLResponse?, Error?) { var data: Data? var response: URLResponse? var error: Error? let semaphore = DispatchSemaphore(value: 0) let dataTask = self.dataTask(with: urlrequest) { data = $0 response = $1 error = $2 semaphore.signal() } dataTask.resume() _ = semaphore.wait(timeout: .distantFuture) return (data, response, error) } } 

我这样打电话

 var request = URLRequest(url: url1) request.httpBody = body request.httpMethod = "PUT" let (_, _, error) = URLSession.shared.synchronousDataTask(urlrequest: request) if let error = error { print("Synchronous task ended with error: \(error)") } else { print("Synchronous task ended without errors.") } 

请小心同步请求,因为它可能导致不良的用户体验,但有时我知道它的必要性。 对于同步请求使用NSURLConnection:

 func synchronousRequest() -> NSDictionary { //creating the request let url: NSURL! = NSURL(string: "exampledomain/...") var request = NSMutableURLRequest(URL: url) request.HTTPMethod = "GET" request.addValue("application/json", forHTTPHeaderField: "Content-Type") var error: NSError? var response: NSURLResponse? let urlData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error) error = nil let resultDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData!, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSDictionary return resultDictionary }