Can I somehow do a synchronous HTTP request via NSURLSession in Swift Can I somehow do a synchronous HTTP request via NSURLSession in Swift swift swift

Can I somehow do a synchronous HTTP request via NSURLSession in Swift


You can use this NSURLSession extension to add a synchronous method:

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

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


Apple thread discussing the same issue.

+ (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;  }  

Answer by Quinn "The Eskimo!" Apple Developer Relations, Developer Technical Support, Core OS/Hardware


Updated one of the answers to use a URLRequest instead, so we can use PUT etc instead.

extension URLSession {    func synchronousDataTask(urlrequest: URLRequest) -> (data: Data?, response: URLResponse?, error: 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)    }}

I'm calling like this.

var request = URLRequest(url: url1)request.httpBody = bodyrequest.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.")}