web-dev-qa-db-fra.com

Définir le nombre de téléchargements simultanés avec NSURLSessionDownloadTask

J'utilise la nouvelle API NSURLSession et j'autorise l'utilisateur à télécharger des fichiers. J'aimerais essayer de dire à ma NSURLSession le nombre de téléchargements simultanés à exécuter, mais je ne vois pas de moyen de le faire. J'aimerais essayer d'éviter de gérer moi-même les tâches de téléchargement, ce serait bien mieux si je pouvais dire au système combien d'en autoriser à la place - ce serait mieux pour mettre en file d'attente les téléchargements en arrière-plan également lorsque mon application n'est pas en cours d'exécution. Y a-t-il un moyen de faire cela?

25
Cory Imdieke

Vous pouvez le définir dans l'objet NSURLSessionConfiguration avec la propriété HTTPMaximumConnectionsPerHost.

19
CouchDeveloper

J'ai trouvé une solution de contournement pour ces délais.

J'ai essayé de télécharger un fichier avec une simulation de connexion lente sur l'appareil (Paramètres -> Développeur -> Conditionneur de lien réseau -> Choisissez un profil -> 3G -> Activer).

Voici mon exemple de code:

- (void) methodForNSURLSession{
  NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  _tasksArray = [[NSMutableArray alloc] init];
  sessionConfig.HTTPMaximumConnectionsPerHost = 3;
  sessionConfig.timeoutIntervalForResource = 120;
  sessionConfig.timeoutIntervalForRequest = 120;
  NSURLSession* session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

  // data tasks
  [self createDownloadTasksWithSession:session];

}

- (void) createDownloadTasksWithSession:(NSURLSession *)session{
  for (int i = 0; i < 100; i++) {
    NSURLSessionDownloadTask *sessionDownloadTask = [session downloadTaskWithURL: [NSURL URLWithString:@"https://discussions.Apple.com/servlet/JiveServlet/showImage/2-20930244-204399/iPhone%2B5%2BProblem2.jpg"]];
    [_tasksArray addObject:sessionDownloadTask];
    [sessionDownloadTask addObserver:self forKeyPath:@"countOfBytesReceived" options:NSKeyValueObservingOptionOld context:nil];
    [sessionDownloadTask resume];
  }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
  if([[change objectForKey:@"old"] integerValue] == 0){
    NSLog(@"task %d: started", [_tasksArray indexOfObject: object]);
  }
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    if (!error) {
      NSLog(@"task %d: finished!", [_tasksArray indexOfObject:task]);
    } else if (error.code == NSURLErrorTimedOut) {
      NSLog(@"task %d: timed out!", [_tasksArray indexOfObject:task]);
    }
}

Et ma sortie:

2014-01-10 10:38:48.769 TestApplication[2442:1803] task 1: started
2014-01-10 10:38:49.517 TestApplication[2442:1803] task 2: started
2014-01-10 10:38:50.273 TestApplication[2442:4b03] task 0: started
2014-01-10 10:40:11.794 TestApplication[2442:5003] task 2: finished!
2014-01-10 10:40:13.924 TestApplication[2442:1803] task 3: started
2014-01-10 10:40:26.221 TestApplication[2442:1d0f] task 1: finished!
2014-01-10 10:40:28.487 TestApplication[2442:1d0f] task 4: started
2014-01-10 10:40:43.007 TestApplication[2442:440f] task 5: timed out!
2014-01-10 10:40:43.009 TestApplication[2442:440f] task 6: timed out!
2014-01-10 10:40:43.011 TestApplication[2442:440f] task 7: timed out!
...

Comme vous pouvez le voir, les tâches commencées expirent au bout de 2 minutes

J'ai joué avec les paramètres timeoutIntervalForResource et timeoutIntervalForRequest et au cas où nous mettions les deux à 0, il sera téléchargé sans délai. Mais je pense que ce n'est pas une bonne idée à cause de la batterie tirée. Je pense que 10 minutes ou quelque chose comme ça sera une bonne valeur pour cela. Mais vous devez définir les deux paramètres sur la même valeur.

Documents Apple:

timeoutIntervalForRequest - L'intervalle de temporisation à utiliser lors de l'attente de données supplémentaires. timeoutIntervalForResource - La durée maximale qu'une demande de ressource doit être autorisée à prendre. (délai d'expiration pour toutes les tâches vers une ressource)

Remarqué chose étrange: au cas où nous définirions timeoutIntervalForResource = 60 et timeoutIntervalForRequest = 30, les tâches expireront après 30 secondes! Mais la plupart d'entre eux ne commenceront même pas!

On dirait que le minuteur pour timeoutIntervalForRequest a démarré lorsque la tâche a repris. Dans ce cas, nous avons repris toutes les tâches en même temps et le délai d'expiration de chaque tâche doit correspondre à un délai d'expiration des ressources.

Aussi, je peux conseiller session wwdc13 705 avec une excellente démo sur la session d'arrière-plan avec la tâche de téléchargement.

13
kaspartus