2016-09-22 2 views
1

J'ai une fonction de recherche de vols dans mon application qui prend trop de temps pour obtenir les données (plus de 25 secondes). Si l'application passe en arrière-plan ou passe en mode veille, la connexion Internet est déconnectée.Tâche d'arrière-plan iOS utilisant NSURLSessionDataTask

J'ai écrit ci-dessous la logique en utilisant l'exemple de la pomme pour faire une demande api continuer même si l'application va à l'arrière-plan, mais ça ne fonctionne pas.

self.session = [self backgroundSession]; 
self.mutableData = [NSMutableData data]; 

NSURL *downloadURL = [NSURL URLWithString:@"http://jsonplaceholder.typicode.com/photos"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; 
self.dataTask = [self.session dataTaskWithRequest:request]; 
[self.dataTask resume]; 

- (NSURLSession *)backgroundSession 
{ 
    static NSURLSession *session = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"]; 
     session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 
    }); 
    return session; 
} 

ci-dessous sont les méthodes déléguées

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask 
didReceiveResponse:(NSURLResponse *)response 
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { 
NSLog(@"response: %@", response.debugDescription); 
NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow; 
    if (completionHandler) { 
     completionHandler(disposition); 
    } 
} 

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask 
    didReceiveData:(NSData *)data { 
    [self.mutableData appendData:data]; 
} 


- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 
{ 
    BLog(); 

    if (error == nil) 
    { 
     NSData *data = nil; 
     if (self.mutableData) { 
      data = [self.mutableData copy]; 
      self.mutableData = nil; 
     } 

     NSError* error; 
     NSArray* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; 
     if (!json) { 
      NSLog(@"Error parsing JSON: %@", error); 
     } else { 
      NSLog(@"Data: %@", json); 
     } 
    } 
    else 
    { 
     NSLog(@"Task: %@ completed with error: %@", task, [error localizedDescription]); 
    } 

    double progress = (double)task.countOfBytesReceived/(double)task.countOfBytesExpectedToReceive; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     self.progressView.progress = progress; 
    }); 

    self.dataTask =nil; 
} 

Tout fonctionne très bien lorsque l'application est au premier plan, mais dès que je mets l'application sur fond se message d'erreur ci-dessous.

Completed with error: Lost connection to background transfer service

+0

Avez-vous essayé d'ajouter la fonction d'extraction d'arrière-plan dans l'onglet "Capacités" de la cible? – Nailer

+0

une fois activer l'option d'extraction d'arrière-plan dans backgroundmodes. xcode - capabilities - Modes d'arrière-plan – Sanju

+0

Oui, je l'ai fait mais j'ai toujours le même message d'erreur. – Jay

Répondre

4

Vous ne pouvez pas utiliser de tâches de données pour les transferts d'arrière-plan. Ceux-ci doivent se faire en utilisant téléchargement tâches:

Download tasks retrieve data in the form of a file, and support background downloads while the app is not running.

Ceci est expliqué dans Apple documentation.

Veuillez également consulter leur background transfer considerations:

With background sessions, because the actual transfer is performed by a separate process and because restarting your app’s process is relatively expensive, a few features are unavailable, resulting in the following limitations...

La clé ici est qu'il est en cours d'exécution dans un processus séparé qui ne peut pas accéder aux données que vous gardez en mémoire. Il doit être routé à travers un fichier.

J'ai recueilli beaucoup d'informations sur le transfert de fond sur iOS dans un (long) blog post.

+0

Merci Krumelur! J'ai modifié le code avec la tâche de téléchargement cela fonctionne bien. – Jay

+0

Lorsque Internet est déconnecté après la demande de downloadTask, la méthode de délégation didCompleteWithError n'est pas appelée. Une fois la connexion Internet rétablie, elle reprend automatiquement. Y at-il un moyen d'obtenir un message d'erreur Internet déconnecté. – Jay

+0

Après avoir lu le document Apple, il semble qu'il n'est pas possible de trouver l'état de la connexion Internet pendant l'exécution de downloadTask. ajouté ci-dessous le code de timeout sessionConfig.timeoutIntervalForRequest = 30.0; sessionConfig.timeoutIntervalForResource = 60.0; La tâche de données – Jay