11

Je crée un NSMutableRequest:délai d'attente NSURLSessionDataTask demandes ultérieures à défaut

self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0]; 

Le délai d'attente est fixé à 10 secondes parce que je ne veux pas l'utilisateur d'attendre trop longtemps pour obtenir une rétroaction. Après que je crée un NSURLSessionDataTask:

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response; 
    if (error) { 
     // this is where I get the timeout 
    } 
    else if (httpResp.statusCode < 200 || httpResp.statusCode >= 300) { 
     // handling error and giving feedback 
    } 
    else { 
     NSError *serializationError = nil; 
     NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&serializationError]; 
    } 
    [task resume]; 
} 

Le problème est le serveur passe en passerelle Délai d'attente et il faut beaucoup de temps. Je reçois l'erreur timeout et je donne un retour à l'utilisateur, mais tous les appels API suivants échouent de la même manière en raison d'une erreur de timeout. La seule façon de l'arrêter est de tuer l'application et recommencer. Y at-il quelque chose que je devrais faire pour tuer la tâche ou la connexion après une erreur de timeout? Si je ne définis pas de délai d'attente et que j'attends de recevoir le code d'erreur du serveur, tous les appels suivants fonctionnent parfaitement (mais l'utilisateur attend beaucoup!).

J'ai essayé d'annuler la tâche:

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response; 
    if (error) { 
     // this is where I get the timeout 
     [task cancel]; 
    } 
    ... 
    [task resume]; 
} 
+0

Je suppose que, vous pourriez avoir besoin de ré-initialiser le 'self.req' s'il y a une erreur/délai d'attente. Pas sûr à ce sujet cependant. – Mrunal

+0

essayez d'appeler les connexions avec l'application POSTMAN en chrome, et voir si vous obtenez toujours l'erreur de délai d'attente ou non –

+0

Êtes-vous Créer cette tâche dans un bloc? Ou un autre fil, autre que le fil principal? –

Répondre

4

Je ne ai pas vous voir reprendre la tâche que vous avez commencé. Vous devez déclarer:

[task resume]; 

Cette ligne Reprend la tâche si elle est suspendue.

Essayez d'appeler le NSURLSession comme suit:

[NSURLSession sharedSessison] instead of self.session 

et annuler la session par:

[[NSURLSession sharedSession]invalidateAndCancel]; 

De la documentation d'Apple:

Lorsque votre application ne nécessite plus une session , l'invalider en appelant invalidateAndCancel (pour annuler les tâches en attente) ou finishTasksAndInvalidate (pour autoriser tâches en attente à terminer avant d'invalider l'objet).

- (void)invalidateAndCancel 

Une fois invalidés, les références aux délégués et les objets sont rappel cassé. Les objets de session ne peuvent pas être réutilisés.

Pour permettre l'exécution de tâches en attente jusqu'à la fin, appelez plutôt finishTasksAndInvalidate.

- (void)finishTasksAndInvalidate 

Cette méthode retourne immédiatement sans attendre les tâches à terminer. Une fois qu'une session est invalidée, de nouvelles tâches ne peuvent pas être créées dans la session, mais les tâches existantes continuent jusqu'à la fin. Une fois la dernière tâche terminée et la dernière session effectuée, les références aux objets délégué et rappel sont rompues. Les objets de session ne peuvent pas être réutilisés.

Pour annuler toutes les tâches en attente, appelez invalidateAndCancel à la place.

+0

Oui, j'ai oublié le résumé ici dans la question. Je vais l'éditer. Et la seule méthode que je puisse appeler pour l'invalider est «annuler». Je ne peux pas voir les autres. J'ai essayé mais cela ne résout pas le problème. Merci –

+0

comment appeler l'annulation? –

+0

J'ai modifié la question. Merci –

0

La cause la plus probable d'un délai d'attente est que DNS a été résolu à une adresse IP qui n'existait pas ou que le serveur s'est bloqué et doit être redémarré. Dans tous les cas, si une demande échoue avec timeout, plus de demandes risquent raisonnablement d'échouer avec timeout.

Vous avez évidemment besoin d'écrire votre application de telle sorte qu'elle puisse survivre quand les serveurs ne répondent pas.

+0

Si je fixe le délai d'attente à 60 au lieu de 10 secondes, je reçois le "Gateway Timeout" du serveur et toute la demande que je fais après que cela fonctionne parfaitement. Le problème est lorsque le délai d'attente se produit avant la réponse du serveur. Toutes les demandes suivantes échouent jusqu'à ce que je tue l'application. –

1

Vous pouvez régler le délai de manière différente comme le code suivant

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; 
sessionConfiguration.timeoutIntervalForRequest = timeout; 
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:nil delegateQueue:nil]; 
1

Le problème que vous êtes le plus probablement rencontrez ici est que votre tâche n'annulait ou remplir et tient donc la session d'accepter des tâches plus . Conformément à la documentation d'Apple

Après avoir créé une tâche, démarrez-la en appelant sa méthode de reprise. La session conserve ensuite une référence forte à la tâche jusqu'à ce que la demande se termine ou échoue;

Comme T_77 suggéré, essayez d'utiliser [NSURLSession sharedSession]

Aussi une chose que je voudrais essayer de le faire à ce stade de temps essaie de savoir s'il y a un cycle retenir créé entre l'objet de la session et la tâche, en utilisant des instruments

Une autre chose qui pourrait se produire est que la demande n'est pas correctement formée et n'est pas en cours d'exécution ou est bloqué. J'avais déjà fait face à un problème similaire lorsque j'ai essayé de charger une URL sur une vue Web. La page ne se chargeait pas et ne renvoyait pas d'erreur. Essayez de vérifier la demande d'URL également une fois.

Merci, Suraj