Elaborazione in background in iOS con le attività
Il modo più semplice per eseguire operazioni in background in iOS consiste nell'interrompere i requisiti di background nelle attività ed eseguire le attività in background. Le attività sono sottoposte a un limite di tempo rigoroso e in genere si ottengono circa 600 secondi (10 minuti) di tempo di elaborazione dopo che un'applicazione è stata spostata in background in iOS 6 e meno di 10 minuti in iOS 7+.
Le attività in background possono essere suddivise in tre categorie:
- Attività in background-Cassaforte: chiamata in qualsiasi punto dell'applicazione in cui si dispone di un'attività che non si vuole interrompere se l'applicazione entra in background.
- Attività DidEnterBackground : chiamata durante il metodo del ciclo di vita dell'applicazione per facilitare la pulizia e il
DidEnterBackground
salvataggio dello stato. - Trasferimenti in background (iOS 7+): tipo speciale di attività in background usata per eseguire trasferimenti di rete in iOS 7. A differenza delle normali attività, i trasferimenti in background non hanno un limite di tempo predeterminato.
Le attività e DidEnterBackground
in background sono sicure da usare sia in iOS 6 che in iOS 7, con alcune piccole differenze. Esaminiamo questi due tipi di attività in modo più dettagliato.
Creazione di attività in background Cassaforte
Alcune applicazioni contengono attività che non devono essere interrotte da iOS in caso di modifica dello stato dell'applicazione. Un modo per proteggere queste attività dall'interruzione consiste nel registrarli con iOS come attività a esecuzione prolungata. È possibile usare questo modello in qualsiasi punto dell'applicazione in cui non si vuole che un'attività venga interrotta se l'utente inserisce l'app in background. Un ottimo candidato per questo modello sarebbe attività come l'invio di informazioni di registrazione di un nuovo utente al server o la verifica delle informazioni di accesso.
Il frammento di codice seguente illustra la registrazione di un'attività da eseguire in background:
nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});
//runs on main or background thread
FinishLongRunningTask(taskID);
UIApplication.SharedApplication.EndBackgroundTask(taskID);
Il processo di registrazione associa un'attività con un identificatore univoco, taskID
, e quindi lo esegue in BeginBackgroundTask
corrispondenza e EndBackgroundTask
chiamate. Per generare l'identificatore, viene eseguita una chiamata al BeginBackgroundTask
metodo sull'oggetto UIApplication
e quindi si avvia l'attività a esecuzione prolungata, in genere in un nuovo thread. Al termine dell'attività, viene chiamato EndBackgroundTask
e passato lo stesso identificatore. Questo è importante perché iOS terminerà l'applicazione se una BeginBackgroundTask
chiamata non dispone di un oggetto corrispondente EndBackgroundTask
.
Importante
Le attività in background possono essere eseguite sul thread principale o su un thread in background, a seconda delle esigenze dell'applicazione.
Esecuzione di attività durante DidEnterBackground
Oltre a creare un'attività a esecuzione prolungata in background, è possibile usare la registrazione per avviare le attività in background quando un'applicazione viene messa in background. iOS fornisce un metodo di evento nella classe AppDelegate chiamato DidEnterBackground
che può essere usato per salvare lo stato dell'applicazione, salvare i dati utente e crittografare il contenuto sensibile prima che un'applicazione entri in background. Un'applicazione ha circa cinque secondi da restituire da questo metodo o verrà terminata. Pertanto, le attività di pulizia che potrebbero richiedere più di cinque secondi per completare possono essere chiamate dall'interno del DidEnterBackground
metodo . Queste attività devono essere richiamate in un thread separato.
Il processo è quasi identico a quello della registrazione di un'attività a esecuzione prolungata. Il frammento di codice seguente illustra questa operazione in azione:
public override void DidEnterBackground (UIApplication application) {
nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});
new Task ( () => {
DoWork();
UIApplication.SharedApplication.EndBackgroundTask(taskID);
}).Start();
}
Si inizia eseguendo l'override AppDelegate
del DidEnterBackground
metodo in , in cui si registra l'attività tramite BeginBackgroundTask
come nell'esempio precedente. Successivamente, viene generato un nuovo thread ed è possibile eseguire l'attività a esecuzione prolungata. Si noti che la EndBackgroundTask
chiamata viene eseguita dall'interno dell'attività a esecuzione prolungata, perché il DidEnterBackground
metodo sarà già restituito.
Importante
iOS usa un meccanismo watchdog per garantire che l'interfaccia utente di un'applicazione rimanga reattiva. Un'applicazione che impiega troppo tempo in DidEnterBackground
non risponderà nell'interfaccia utente. L'avvio delle attività da eseguire in background consente di DidEnterBackground
tornare in modo tempestivo, mantenendo reattiva l'interfaccia utente e impedendo al watchdog di uccidere l'applicazione.
Gestione dei limiti di tempo delle attività in background
iOS pone limiti rigorosi sulla durata dell'esecuzione di un'attività in background e, se la EndBackgroundTask
chiamata non viene effettuata entro il tempo assegnato, l'applicazione verrà terminata. Tenendo traccia del tempo rimanente in background e usando i gestori di scadenza quando necessario, è possibile evitare che iOS termini l'applicazione.
Accesso all'ora in background rimanente
Se un'applicazione con attività registrate viene spostata in background, le attività registrate otterranno circa 600 secondi da eseguire. È possibile controllare il tempo necessario per il completamento dell'attività usando la proprietà statica BackgroundTimeRemaining
della UIApplication
classe . Il codice seguente ci darà il tempo, in secondi, che l'attività in background è rimasta:
double timeRemaining = UIApplication.SharedApplication.BackgroundTimeRemaining;
Evitare la terminazione dell'app con i gestori di scadenza
Oltre a concedere l'accesso alla proprietà, iOS offre un modo normale per gestire la BackgroundTimeRemaining
scadenza del tempo in background tramite un gestore di scadenza. Si tratta di un blocco facoltativo di codice che verrà eseguito quando l'ora assegnata per un'attività sta per scadere. Il codice nel gestore di scadenza chiama EndBackgroundTask
e passa l'ID attività, che indica che l'app si comporta correttamente e impedisce a iOS di terminare l'app anche se l'attività scade. EndBackgroundTask
deve essere chiamato all'interno del gestore di scadenza, nonché nel normale corso di esecuzione.
Il gestore di scadenza viene espresso come funzione anonima usando un'espressione lambda, come illustrato di seguito:
Task.Factory.StartNew( () => {
//expirationHandler only called if background time allowed exceeded
var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() => {
Console.WriteLine("Exhausted time");
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
while(myFlag == true)
{
Console.WriteLine(UIApplication.SharedApplication.BackgroundTimeRemaining);
myFlag = SomeCalculationNeedsMoreTime();
}
//Only called if loop terminated due to myFlag and not expiration of time
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
Anche se i gestori di scadenza non sono necessari per l'esecuzione del codice, è consigliabile usare sempre un gestore di scadenza con un'attività in background.
Attività in background in iOS 7+
Il cambiamento più importante in iOS 7 per quanto riguarda le attività in background non è il modo in cui vengono implementate le attività, ma quando vengono eseguite.
Tenere presente che prima di iOS 7, un'attività in esecuzione in background aveva 600 secondi per il completamento. Un motivo per questo limite è che un'attività in esecuzione in background manterrà attivo il dispositivo per la durata dell'attività:
L'elaborazione in background di iOS 7 è ottimizzata per una maggiore durata della batteria. In iOS 7, l'esecuzione in background diventa opportunistica: invece di mantenere sveglio il dispositivo, le attività rispettano quando il dispositivo passa alla sospensione e, invece, esegue l'elaborazione in blocchi quando il dispositivo si riattiva per gestire chiamate telefoniche, notifiche, messaggi di posta elettronica in arrivo e altre interruzioni comuni. Il diagramma seguente fornisce informazioni dettagliate sul modo in cui un'attività potrebbe essere suddivisa:
Poiché il tempo di esecuzione dell'attività non è più continuo, le attività che eseguono trasferimenti di rete devono essere gestite in modo diverso in iOS 7. Gli sviluppatori sono invitati a usare l'API NSURlSession
per gestire i trasferimenti di rete. La sezione successiva è una panoramica dei trasferimenti in background.
Trasferimenti in background
Il backbone dei trasferimenti in background in iOS 7 è la nuova NSURLSession
API. NSURLSession
consente di creare attività per:
- Trasferire il contenuto tramite interruzioni di rete e dispositivo.
- Caricare e scaricare file di grandi dimensioni ( Servizio trasferimento in background ).
Esaminiamo più in dettaglio il funzionamento di questa operazione.
NSURLSession API
NSURLSession
è un'API potente per il trasferimento del contenuto in rete. Fornisce un set di strumenti per gestire il trasferimento dei dati tramite interruzioni di rete e modifiche negli stati dell'applicazione.
L'API NSURLSession
crea una o più sessioni, che a loro volta generano attività per spostare blocchi di dati correlati attraverso la rete. Le attività vengono eseguite in modo asincrono per trasferire i dati in modo rapido e affidabile. Poiché NSURLSession
è asincrono, ogni sessione richiede un blocco del gestore di completamento per informare il sistema e l'applicazione al termine di un trasferimento.
Per eseguire un trasferimento di rete valido sia in pre-iOS 7 che post-iOS 7, verificare se è NSURLSession
disponibile per accodare i trasferimenti e usare una normale attività in background per eseguire il trasferimento in caso contrario:
if ([NSURLSession class]) {
// Create a background session and enqueue transfers
}
else {
// Start a background task and transfer directly
// Do NOT make calls to update the UI here!
}
Importante
Evitare di effettuare chiamate per aggiornare l'interfaccia utente in background nel codice conforme a iOS 6, perché iOS 6 non supporta gli aggiornamenti dell'interfaccia utente in background e terminerà l'applicazione.
L'API NSURLSession
include un set completo di funzionalità per gestire l'autenticazione, gestire i trasferimenti non riusciti e segnalare errori sul lato client, ma non sul lato server. Consente di colmare le interruzioni in fase di esecuzione delle attività introdotte in iOS 7 e offre anche il supporto per il trasferimento di file di grandi dimensioni in modo rapido e affidabile. Nella sezione successiva viene esaminata questa seconda funzionalità.
Servizio trasferimento in background
Prima di iOS 7, il caricamento o il download di file in background non era affidabile. Le attività in background ottengono un tempo limitato per l'esecuzione, ma il tempo necessario per trasferire un file varia in base alla rete e alle dimensioni del file. In iOS 7 è possibile usare un per NSURLSession
caricare e scaricare correttamente file di grandi dimensioni. NSURLSession
Il particolare tipo di sessione che gestisce i trasferimenti di rete di file di grandi dimensioni in background è noto come Servizio trasferimento in background.
I trasferimenti avviati tramite il servizio trasferimento in background vengono gestiti dal sistema operativo e forniscono API per gestire l'autenticazione e gli errori. Poiché i trasferimenti non sono vincolati da un limite di tempo arbitrario, possono essere usati per caricare o scaricare file di grandi dimensioni, aggiornare automaticamente il contenuto in background e altro ancora. Per informazioni dettagliate su come implementare il servizio, vedere la procedura dettagliata per il trasferimento in background.
Il servizio trasferimento in background è spesso associato a Background Fetch o Remote Notifications per consentire alle applicazioni di aggiornare il contenuto in background. Nelle due sezioni successive viene presentato il concetto di registrazione di intere applicazioni da eseguire in background sia in iOS 6 che in iOS 7.