Freigeben über


iOS-Hintergrundverarbeitung mit Aufgaben

Die einfachste Möglichkeit zum Ausführen von Hintergrundinformationen unter iOS besteht darin, Ihre Hintergrundanforderungen in Aufgaben zu unterteilen und die Aufgaben im Hintergrund auszuführen. Aufgaben unterliegen einem strengen Zeitlimit und erhalten in der Regel etwa 600 Sekunden (10 Minuten) Verarbeitungszeit, nachdem eine Anwendung unter iOS 6 in den Hintergrund verschoben wurde, und weniger als 10 Minuten unter iOS 7 und höher.

Hintergrundaufgaben können in drei Kategorien unterteilt werden:

  1. Hintergrundsichere Aufgaben : Wird überall in der Anwendung aufgerufen, an der sie eine Aufgabe haben, die nicht unterbrochen werden soll, wenn die Anwendung in den Hintergrund eintritt.
  2. DidEnterBackground-Aufgaben : Wird während der Methode des DidEnterBackground Anwendungslebenszyklus aufgerufen, um das Bereinigen und Speichern des Zustands zu unterstützen.
  3. Hintergrundübertragungen (iOS 7 und höher): Eine spezielle Art von Hintergrundaufgabe, die zum Ausführen von Netzwerkübertragungen unter iOS 7 verwendet wird. Im Gegensatz zu regulären Aufgaben haben Hintergrundübertragungen kein vorab festgelegtes Zeitlimit.

Hintergrundsicher und DidEnterBackground Aufgaben können sowohl unter iOS 6 als auch unter iOS 7 sicher verwendet werden, mit einigen geringfügigen Unterschieden. Lassen Sie uns diese beiden Arten von Aufgaben genauer untersuchen.

Erstellen von Background-Safe Tasks

Einige Anwendungen enthalten Aufgaben, die von iOS nicht unterbrochen werden sollten, wenn sich der Anwendungszustand ändert. Eine Möglichkeit, diese Aufgaben vor Unterbrechungen zu schützen, besteht darin, sie bei iOS als lang andauernde Aufgaben zu registrieren. Sie können dieses Muster überall in Ihrer Anwendung verwenden, wo Sie nicht möchten, dass eine Aufgabe unterbrochen wird, wenn der Benutzer die App im Hintergrund platziert. Ein guter Kandidat für dieses Muster wären Aufgaben wie das Senden der Registrierungsinformationen eines neuen Benutzers an Ihren Server oder das Überprüfen von Anmeldeinformationen.

Der folgende Codeausschnitt veranschaulicht die Registrierung einer Aufgabe, die im Hintergrund ausgeführt werden soll:

nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});

//runs on main or background thread
FinishLongRunningTask(taskID);

UIApplication.SharedApplication.EndBackgroundTask(taskID);

Der Registrierungsprozess koppelt eine Aufgabe mit einem eindeutigen Bezeichner , taskIDund umschließt sie dann in Übereinstimmungen BeginBackgroundTask und EndBackgroundTask Aufrufe. Um den Bezeichner zu generieren, rufen wir die BeginBackgroundTask -Methode für das UIApplication -Objekt auf und starten dann den Task mit langer Ausführungsdauer, in der Regel in einem neuen Thread. Wenn die Aufgabe abgeschlossen ist, rufen EndBackgroundTask wir auf und übergeben denselben Bezeichner. Dies ist wichtig, da iOS die Anwendung beendet, wenn ein BeginBackgroundTask Aufruf nicht über einen entsprechenden EndBackgroundTaskverfügt.

Wichtig

Hintergrundsichere Aufgaben können abhängig von den Anforderungen der Anwendung entweder im Standard-Thread oder in einem Hintergrundthread ausgeführt werden.

Ausführen von Aufgaben während didEnterBackground

Zusätzlich zur Hintergrundsicherheit einer lang andauernden Aufgabe kann die Registrierung verwendet werden, um Aufgaben zu starten, während eine Anwendung im Hintergrund platziert wird. iOS stellt eine Ereignismethode in der AppDelegate-Klasse namens DidEnterBackground bereit, die verwendet werden kann, um den Anwendungsstatus zu speichern, Benutzerdaten zu speichern und vertrauliche Inhalte zu verschlüsseln, bevor eine Anwendung in den Hintergrund wechselt. Eine Anwendung hat etwa fünf Sekunden Zeit, um von dieser Methode zurückzugeben, oder sie wird beendet. Daher können Bereinigungsaufgaben, deren Ausführung mehr als fünf Sekunden dauern kann, innerhalb der DidEnterBackground -Methode aufgerufen werden. Diese Aufgaben müssen in einem separaten Thread aufgerufen werden.

Der Prozess ist nahezu identisch mit dem Vorgang, bei dem eine Aufgabe mit langer Ausführungszeit registriert wird. Der folgende Codeausschnitt veranschaulicht dies in Aktion:

public override void DidEnterBackground (UIApplication application) {
  nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});
  new Task ( () => {
    DoWork();
    UIApplication.SharedApplication.EndBackgroundTask(taskID);
  }).Start();
}

Wir beginnen mit dem Überschreiben der DidEnterBackground -Methode in , AppDelegatewo wir unsere Aufgabe wie im vorherigen Beispiel über BeginBackgroundTask registrieren. Als Nächstes erstellen wir einen neuen Thread und führen unsere lang andauernde Aufgabe aus. Beachten Sie, dass der EndBackgroundTask Aufruf jetzt aus dem Task mit langer Ausführungsdauer erfolgt, da die DidEnterBackground Methode bereits zurückgegeben wurde.

Wichtig

iOS verwendet einen Watchdog-Mechanismus , um sicherzustellen, dass die Benutzeroberfläche einer Anwendung reaktionsfähig bleibt. Eine Anwendung, die zu viel Zeit in DidEnterBackground verbringt, reagiert auf der Benutzeroberfläche nicht mehr. Das Starten von Aufgaben, die im Hintergrund ausgeführt werden sollen, ermöglicht DidEnterBackground eine zeitnahe Rückgabe, sodass die Benutzeroberfläche reaktionsfähig bleibt und verhindert wird, dass der Watchdog die Anwendung beendet.

Behandeln von Zeitlimits für Hintergrundaufgaben

iOS legt strikte Beschränkungen fest, wie lange eine Hintergrundaufgabe ausgeführt werden kann, und wenn der EndBackgroundTask Aufruf nicht innerhalb der zugewiesenen Zeit erfolgt, wird die Anwendung beendet. Indem wir die verbleibende Hintergrundzeit nachverfolgen und bei Bedarf Ablaufhandler verwenden, können wir verhindern, dass iOS die Anwendung beendet.

Zugriff auf verbleibende Hintergrundzeit

Wenn eine Anwendung mit registrierten Aufgaben in den Hintergrund verschoben wird, erhalten die registrierten Aufgaben etwa 600 Sekunden Zeit, um sie auszuführen. Mithilfe der statischen BackgroundTimeRemaining Eigenschaft der UIApplication -Klasse können Wir überprüfen, wie viel Zeit der Task zum Abschließen hat. Der folgende Code gibt uns die Zeit in Sekunden, die unsere Hintergrundaufgabe verlassen hat:

double timeRemaining = UIApplication.SharedApplication.BackgroundTimeRemaining;

Vermeiden der App-Beendigung mit Ablaufhandlern

Zusätzlich zum Zugriff auf die BackgroundTimeRemaining Eigenschaft bietet iOS eine ordnungsgemäße Möglichkeit, den Ablauf der Hintergrundzeit über einen Ablaufhandler zu behandeln. Dies ist ein optionaler Codeblock, der ausgeführt wird, wenn die für einen Task zugewiesene Zeit bald abläuft. Code im Ablaufhandler ruft EndBackgroundTask auf und übergibt die Aufgaben-ID, was angibt, dass sich die App gut verhält und verhindert, dass iOS die App beendet, auch wenn die Aufgabe nicht mehr zeitlos ist. EndBackgroundTask muss innerhalb des Ablaufhandlers sowie im normalen Ausführungsverlauf aufgerufen werden.

Der Ablaufhandler wird als anonyme Funktion mithilfe eines Lambdaausdrucks ausgedrückt, wie unten dargestellt:

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);
});

Während Ablaufhandler für die Ausführung des Codes nicht erforderlich sind, sollten Sie immer einen Ablaufhandler mit einer Hintergrundaufgabe verwenden.

Hintergrundaufgaben in iOS 7 und höher

Die größte Änderung in iOS 7 in Bezug auf Hintergrundaufgaben besteht nicht darin, wie die Aufgaben implementiert werden, sondern wann sie ausgeführt werden.

Denken Sie daran, dass vor iOS 7 eine Im Hintergrund ausgeführte Aufgabe 600 Sekunden lang war. Ein Grund für diesen Grenzwert ist, dass eine im Hintergrund ausgeführte Aufgabe das Gerät für die Dauer der Aufgabe wach hält:

Diagramm der Aufgabe, die App vor iOS 7 wach zu halten

Die Hintergrundverarbeitung von iOS 7 ist für eine längere Akkulaufzeit optimiert. In iOS 7 wird die Hintergrundbearbeitung opportunistisch: Anstatt das Gerät wach zu halten, berücksichtigen Aufgaben, wenn das Gerät in den Standbymodus wechselt, und führen ihre Verarbeitung stattdessen in Blöcken durch, wenn das Gerät wieder aktiviert wird, um Telefonanrufe, Benachrichtigungen, eingehende E-Mails und andere häufige Unterbrechungen zu verarbeiten. Das folgende Diagramm zeigt, wie eine Aufgabe untergliedert werden kann:

Diagramm der Aufgabe, die nach iOS 7 in Blöcke unterteilt wird

Da die Taskausführungszeit nicht länger fortlaufend ist, müssen Aufgaben, die Netzwerkübertragungen durchführen, in iOS 7 unterschiedlich behandelt werden. Entwicklern wird empfohlen, die API zum Verarbeiten von NSURlSession Netzwerkübertragungen zu verwenden. Der nächste Abschnitt enthält eine Übersicht über Hintergrundübertragungen.

Hintergrundübertragungen

Das Rückgrat von Hintergrundübertragungen in iOS 7 ist die neue NSURLSession API. NSURLSession ermöglicht es uns, Aufgaben für Folgendes zu erstellen:

  1. Übertragen von Inhalten über Netzwerk- und Geräteunterbrechungen.
  2. Hochladen und Herunterladen großer Dateien ( Hintergrundübertragungsdienst ).

Sehen wir uns genauer an, wie dies funktioniert.

NSURLSession-API

NSURLSession ist eine leistungsstarke API zum Übertragen von Inhalten über das Netzwerk. Es bietet eine Reihe von Tools, um die Übertragung von Daten durch Netzwerkunterbrechungen und Änderungen in Den Anwendungszuständen zu verarbeiten.

Die NSURLSession API erstellt eine oder mehrere Sitzungen, die wiederum Aufgaben erzeugen, um Blöcke verwandter Daten über das Netzwerk zu übertragen. Aufgaben werden asynchron ausgeführt, um Daten schnell und zuverlässig zu übertragen. Da NSURLSession asynchron ist, erfordert jede Sitzung einen Abschlusshandlerblock, um dem System und der Anwendung mitzuteilen, wann eine Übertragung abgeschlossen ist.

Wenn Sie eine Netzwerkübertragung durchführen möchten, die sowohl unter pre-iOS 7 als auch nach iOS 7 gültig ist, überprüfen Sie, ob eine NSURLSession für die Warteschlange von Übertragungen verfügbar ist, und verwenden Sie eine reguläre Hintergrundaufgabe, um die Übertragung auszuführen, wenn dies nicht der Gleiche ist:

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!
}

Wichtig

Vermeiden Sie Aufrufe zum Aktualisieren der Benutzeroberfläche aus dem Hintergrund in iOS 6-kompatiblem Code, da iOS 6 keine Hintergrund-UI-Updates unterstützt und die Anwendung beendet.

Die NSURLSession API enthält eine Vielzahl von Features zum Behandeln von Authentifizierung, Verwalten fehlerhafter Übertragungen und Melden clientseitiger - aber nicht serverseitiger - Fehler. Es hilft, die in iOS 7 eingeführten Unterbrechungen der Taskausführung zu überbrücken, und bietet auch Unterstützung für die schnelle und zuverlässige Übertragung großer Dateien. Im nächsten Abschnitt wird dieses zweite Feature erläutert.

Hintergrundübertragungsdienst

Vor iOS 7 war das Hochladen oder Herunterladen von Dateien im Hintergrund unzuverlässig. Hintergrundaufgaben haben eine begrenzte Zeit für die Ausführung, aber die Zeit, die zum Übertragen einer Datei benötigt wird, variiert je nach Netzwerk und Größe der Datei. In iOS 7 können wir eine NSURLSession verwenden, um große Dateien erfolgreich hoch- und herunterzuladen. Der spezielle NSURLSession Sitzungstyp, der Netzwerkübertragungen großer Dateien im Hintergrund verarbeitet, wird als Hintergrundübertragungsdienst bezeichnet.

Übertragungen, die mit dem Hintergrundübertragungsdienst initiiert werden, werden vom Betriebssystem verwaltet und stellen APIs bereit, um Authentifizierung und Fehler zu behandeln. Da Übertragungen nicht an ein beliebiges Zeitlimit gebunden sind, können sie zum Hochladen oder Herunterladen großer Dateien, automatischer Aktualisierung von Inhalten im Hintergrund und mehr verwendet werden. Ausführliche Informationen zum Implementieren des Diensts finden Sie in der exemplarischen Vorgehensweise zur Hintergrundübertragung .

Der Hintergrundübertragungsdienst wird häufig mit Hintergrundabrufen oder Remotebenachrichtigungen gekoppelt, um Anwendungen beim Aktualisieren von Inhalten im Hintergrund zu unterstützen. In den nächsten beiden Abschnitten wird das Konzept der Registrierung ganzer Anwendungen vorgestellt, die im Hintergrund sowohl unter iOS 6 als auch unter iOS 7 ausgeführt werden.