2016-11-17 2 views
5

C'est ce que la documentation d'Apple dit au sujet de la méthode suspend de NSURLSessionTask classeNSURLSessionTask. Suspendre ne fonctionne pas

Une tâche, alors qu'il était suspendu, ne produit pas le trafic réseau et ne sont pas soumis à temps morts.

Ok. Donc, je courais le code simple suivant:

 let url = NSURL(string: "http://httpbin.org/delay/10")! 
     let urlRequest = NSURLRequest(URL: url) 

     self.task = NSURLSession.sharedSession().dataTaskWithURL(urlRequest.URL!, completionHandler: { 

      data, response, error in print("completion ERROR \(error)") 
     }) 

     self.task.resume() 

     print("Start") 
     delay(5, closure: { 

      self.task.suspend() 

      print("Suspend") 
     }) 

Fonction delay est tout simplement une enveloppe autour dispatch_after et une demande de http://httpbin.org/delay/10 donne une réponse au bout de 10 secondes. Au milieu d'attendre la réponse, je suspends la tâche. Cependant cela ne fonctionne pas. En 60 secondes, le bloc d'achèvement est appelé avec une erreur de dépassement de délai. Quelqu'un peut-il expliquer ce qui ne va pas?

+0

Pouvez-vous montrer l'emballage autour de 'dispatch_after'? –

Répondre

5

Cela semble être un comportement normal, mais une documentation plus définitive d'Apple serait utile pour clarifier ce que nous voyons.

La documentation d'Apple ne fournit pas d'explication détaillée sur le fonctionnement de la suspension ou sur son utilisation. Cependant, mon point de vue (basé sur des essais et de la recherche) est que suspend() devrait seulement être utilisé pour le téléchargement tâches. Les tâches de données ne doivent utiliser que resume() (pour démarrer la tâche) et cancel(), le cas échéant. Mes tests, utilisant Xcode et Charles Proxy, ont révélé qu'une tâche de données suspendue n'a aucun effet sur le trafic réseau comme indiqué dans la documentation d'Apple. En d'autres termes, le trafic réseau est produit.

J'observé deux choses à l'aide de suspendre et les tâches de données:

1) Si elle est appelée juste après la reprise, il n'a pas d'effet sur la tâche de données. Il ne suspend pas le trafic réseau et, en l'absence de problèmes côté réseau ou serveur, une réponse réussie est reçue dans le rappel.

2) Si elle est appelée dans le rappel dispatch.asyncAfter, elle ne suspend toujours pas le trafic réseau, mais le rappel reçoit une erreur de "requête timeout" au lieu d'une réponse réussie. Selon Charles Proxy, la demande est couronnée de succès. C'est ce résultat qui me porte à croire que suspend() ne devrait pas être utilisé avec des tâches de données. Le résultat de ce rappel est essentiellement inutile à mon avis.

Annulation d'une tâche de données:

cancel() fonctionne comme prévu. Le client (vous) ferme la connexion avant d'obtenir une réponse complète du serveur. Cela peut être fait juste après avoir appelé resume() ou plus tard (avant que la demande soit terminée bien sûr).

+0

"La requête a expiré."? Qu'est-ce que c'est? L'erreur est-elle passée dans le bloc d'achèvement? Donc, cela fonctionne pour vous comme pour moi, donc c'est un comportement normal pour une tâche suspendue, non? Si oui, alors pourquoi avons-nous besoin de suspendre du tout? Ou ai-je mal compris quelque chose? –

+0

@AndreyChernukha Désolé, il semble que j'ai mal interprété votre question. Je pensais que vous ne voyiez pas le message "Suspend" dans la console. –

+0

@AndreyChernukha Vous avez raison, j'ai mis à jour ma réponse pour fournir plus de détails. Il semble que ce soit un comportement normal pour une tâche de données. Une tâche de téléchargement ne sera vraisemblablement pas transmise au bloc d'achèvement tant que la tâche n'aura pas été reprise et complétée. –

0

J'accepte que suspendent() n'a pas d'effet sur URLSessionDataTask

    let dataTask = URLSession.shared.dataTask(with: request) { (data, urlResponse, error) in       
        print("response is received all the time") 
        } 
       } 
       dataTask.resume() 
       dataTask.suspend() 

Cependant lorsque je tente son annulation ne

let dataTask = URLSession.shared.dataTask(with: request) { (data, urlResponse, error) in       
        print("response is cancelled") 
        } 
       } 
       dataTask.resume() 
       dataTask.cancel()