2014-11-21 12 views
5

Ho un'app in cui devo scaricare un numero elevato di file, da 400 a 900 file che sono circa 1 GB in totale.Scarica un numero elevato di file in background in iOS

Qual è l'approccio migliore per raggiungere questo obiettivo?

  1. Uno NSURLSession e tutti i task sono stati inseriti in esso?
  2. Uno NSURLSession e accodare attività per pacchetti (10 per 10 ad esempio)?
  3. Più NSURLSession con diverse code?

In realtà ho un NSURLSession all'interno di tutti i task (uno per ogni file) accodato, ma a volte ottengo un Lost connection to background transfer service.

Ecco il mio codice:

if([[UIDevice currentDevice] isMultitaskingSupported]) 
{ 
    __block UIBackgroundTaskIdentifier bgTask; 

    UIApplication *application = [UIApplication sharedApplication]; 

    bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 

     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     NSString *uuidString; 
     CFUUIDRef uuid = CFUUIDCreate(nil); 
     uuidString = CFBridgingRelease(CFUUIDCreateString(nil, uuid)); 
     CFRelease(uuid); 
     //   } 

     NSURLSessionConfiguration *sessionConfiguration; 

     if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) 
     { 
      sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.fiveflamesmobile.bakgroundDownload"]; 
     } 
     else 
     { 
      sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.fiveflamesmobile.bakgroundDownload"]; 
     } 
     sessionConfiguration.HTTPMaximumConnectionsPerHost = 5; 
     sessionConfiguration.sessionSendsLaunchEvents = YES; 
     sessionConfiguration.discretionary = YES; 
     sessionConfiguration.timeoutIntervalForResource = 0; //NO timeout 
     sessionConfiguration.timeoutIntervalForRequest = 0; //No timeout 
     sessionConfiguration.networkServiceType = NSURLNetworkServiceTypeBackground; 

     self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration 
                delegate:self 
               delegateQueue:nil]; 

     NSLog(@"##### ------- Sesion created succesfully"); 

     // [self batchDownloading]; 

     for (id<FFDownloadFileProtocol> file in self.selectedCatalogProducto.downloadInfo.arrayFiles) 
     { 
      [self startDownloadFile:file]; 
     } 

     NSLog(@"##### ------- Download tasks created successfully ------"); 

     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }); 
} 

} 
+0

'Un NSURLSession e compiti di accodamento da pacchetti (10 per 10, per esempio)? 'suona bene. –

+0

@AnoopVaidya perché lo dici? Dovrebbe solo creare una singola sessione in background e aggiungere le sue attività di download. Non vedo alcun valore nell'approccio 10x10. – Rob

+0

sei riuscito a scaricare tutti i file in background? – Mahesh

risposta

1

One NSURLSession - perché si vuole solo gestire le cose a base di sessione solo una volta (autenticazione, ad esempio).

One NSOperationQueue: con più operazioni in esecuzione contemporaneamente. (Vedi proprietà operationCount). Potrebbe essere un po 'complicato implementare una NSOperation per la prima volta, ma sono sicuro che sarebbe la soluzione migliore. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperationQueue_class/index.html

http://nshipster.com/nsoperation/

Oh, e dal modo in cui, questo è un approccio altamente orientato agli oggetti, che è sempre bello =)

+2

No, no, no! Sono un grande fan del wrapping delle richieste di rete in 'NSOperation', ma questo è l'unico e solo scenario in cui si fa assolutamente _non_ per farlo. Una configurazione di sessione in background è quella in cui le richieste continuano ad essere eseguite molto tempo dopo che l'app è terminata e dopo che 'NSOperationQueue' e gli oggetti' NSOperation' associati sono stati distrutti. Inoltre, a differenza degli oggetti di configurazione di sessione standard, dove avere "maxConcurrentOperationCount" offre un valore reale, qui ci si mette di mezzo. Con le sessioni in background, si desidera creare immediatamente un'istanza di tutte le richieste di download! – Rob

+0

Ok, questo ha molto senso. In questo modo, anche se l'app è sospesa, la richiesta di rete dovrebbe continuare a essere caricata. Destra? Purtroppo però, per questo motivo, sarebbe necessario disporre di due modi diversi per implementare il download. Il modo operativo funzionerebbe solo con una sessione in background, giusto? – fat

+0

Le attività in background continuano a essere eseguite non solo quando l'app è sospesa, ma anche dopo che l'app è stata completamente terminata (ad esempio se il sistema operativo lo mette in pausa a causa della pressione della memoria). L'unica cosa di cui il daemon in background è a conoscenza sono le attività, e qualsiasi coda di operazioni (e qualsiasi cosa in sospeso in coda) sarà da tempo scomparsa. Quindi la coda di operazioni è favolosa per le sessioni in primo piano, ma interferirà solo con le sessioni in background. Quindi il "modo operativo funzionerebbe solo con le sessioni" _non-background_ (cioè predefinito o effimero). (Suppongo che sia quello che volevi dire Lol.) – Rob

Problemi correlati