Ho avuto un problema molto simile in cui l'attività in background si avviava ma poi sembrava in pausa. L'attività dovrebbe quindi essere completata quando l'applicazione ritorna in primo piano.
ho verificato che questo è stato il caso per registrare i dati trasmessi dal -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
Ho trovato che il modo per aggirare questo problema è a che fare con il modo di archiviare, gestire ed eseguire i gestori di completamento.
Nel mio caso il processo inizia con
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
[self.fmStore performBackgroundRefresh:^(UIBackgroundFetchResult result) {
//Set application badge if new data is available
if (result==UIBackgroundFetchResultNewData) [UIApplication sharedApplication].applicationIconBadgeNumber++;
completionHandler(result);
}];
}
in cui una notifica remota avvia il processo di download.
Il metodo che gestisce il download restituisce un valore dipendente dalla disponibilità di nuovi dati
-(void)performBackgroundRefresh:(void (^)(UIBackgroundFetchResult))completion{
if(newData) completion(UIBackgroundFetchResultNewData);
else completion(UIBackgroundFetchResultNoData);
}
A questo punto si ritorna al ApplicationDelegate in cui il gestore di completamento viene memorizzato
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
//Store completion handler for background session
self.sessionCompletionHandler=completionHandler;
}
Infine , questo pezzo di codice viene eseguito che chiama il gestore di completamento e crea le notifiche appropriate
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
[session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if (![downloadTasks count]) {
FM_AppDelegate *appDelegate=(FM_AppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.sessionCompletionHandler) {
void (^completionHandler)() = appDelegate.sessionCompletionHandler;
appDelegate.sessionCompletionHandler = nil;
completionHandler();
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"ContentRefreshNotification" object:Nil];
}];
}
}];
}
Questo processo avanti e indietro si verifica nel mio caso poiché NSURLSession esiste in un oggetto che è una proprietà di ApplicationDelegate. Se si implementa NSURLSession come proprietà di ApplicationDelegate stesso, tutto questo codice esisterà nello stesso file.
Spero che questo aiuti, ma se avete bisogno di ulteriori informazioni si prega di vedere questi due tutorial 1 e 2 come il mio codice è basato su ciò che ho letto in questi.
Sono di fronte allo stesso problema. Sto passando una serie di elementi e il metodo di delega viene attivato solo quando rilancio l'app. –
I callback sono incoerenti e i download impiegano troppo tempo per iniziare. Con piccoli file l'ho provato con il simulatore e ho scaricato alcuni piccoli file di immagine. I callback per il download completato si attivano dopo che i download sono stati completati 2 o 3 minuti fa. causa il ritardo per l'avvio del prossimo file da scaricare. Il problema si presenta quando porto la mia app in background. In primo piano le stesse funzioni funzionano bene. – Sulabh
Segui tutte le istruzioni in https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html#//apple_ref/doc/uid/TP40013509-SW44 (Trasferimento in background considerazioni)? Voglio dire, usi la configurazione della sessione in background e implementi tutte le callback necessarie in appDelegate e NSURLSessionDelegate? – user2260054