Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

I can do an asynchronous request via the following code:

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

But what about synchronous request?

like image 399
FrozenHeart Avatar asked Nov 06 '14 16:11

FrozenHeart


People also ask

Is HTTP request synchronous?

HTTP is a synchronous protocol: the client issues a request and waits for a response. If you are using non-blocking (aka async) IO, the current thread of the client does not really have to wait, but can do other things (see above).

Is requests get synchronous?

Yes, requests. get is a synchronous operation. It waits for the page contents to be pulled into python as str. The time difference you see is indeed due to the execution of javascipt and the fetching of additional files in the browser.


2 Answers

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)     } } 
like image 133
Nick Keets Avatar answered Sep 18 '22 16:09

Nick Keets


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

like image 43
Umar Farooque Avatar answered Sep 18 '22 16:09

Umar Farooque