Puis-je effectuer une requête HTTP synchrone via NSURLSession dans Swift?

Puis-je effectuer une requête HTTP synchrone via NSURLSession dans Swift?

Je peux faire une requête asynchrone via le code suivant:

 if let url = NSURL(ssortingng: "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 [Ssortingng: AnyObject] if jsonError != nil { return } // ... } task.resume() } 

Mais qu’en est-il de la demande synchrone?

Merci d’avance.

Vous pouvez utiliser cette extension NSURLSession pour append une méthode synchrone:

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

Mise à jour pour 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) } } 

Fil Apple traitant du même problème.

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

Réponse de Quinn “The Eskimo!” Relations avec les développeurs Apple, support technique pour les développeurs, système d’exploitation / matériel de base

Mise à jour de l’une des réponses pour utiliser une URLRequest à la place, nous pouvons donc utiliser PUT, etc. à la place.

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

J’appelle comme ça

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

Soyez prudent avec les requêtes synchrones car cela peut entraîner une mauvaise expérience de l’utilisateur mais je sais parfois qu’il est nécessaire. Pour les requêtes synchrones, utilisez NSURLConnection:

 func synchronousRequest() -> NSDictionary { //creating the request let url: NSURL! = NSURL(ssortingng: "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 }