Sdílet prostřednictvím


Zpracování úloh na pozadí v iOSu s úkoly

Nejjednodušším způsobem, jak provádět pozadí v iOSu, je rozdělit požadavky na pozadí na úlohy a spustit úlohy na pozadí. Úkoly jsou pod přísným časovým limitem a obvykle získáte přibližně 600 sekund (10 minut) doby zpracování po přesunutí aplikace na pozadí v iOSu 6 a méně než 10 minut v iOSu 7+.

Úlohy na pozadí je možné rozdělit do tří kategorií:

  1. Úlohy Sejf na pozadí – Volá se kdekoli v aplikaci, kde máte úkol, který nechcete přerušit, pokud aplikace přejde na pozadí.
  2. DidEnterBackground Tasks – Volá se během DidEnterBackground metody životního cyklu aplikace, která pomáhá při čištění a ukládání stavu.
  3. Přenosy na pozadí (iOS 7+) – speciální typ úlohy na pozadí sloužící k provádění síťových přenosů v iOSu 7. Na rozdíl od běžných úloh nemají přenosy na pozadí předem určený časový limit.

Bezpečné pozadí a DidEnterBackground úlohy jsou bezpečné pro použití v iOSu 6 i iOSu 7 s některými drobnými rozdíly. Pojďme tyto dva typy úkolů podrobněji prozkoumat.

Vytváření úloh Sejf na pozadí

Některé aplikace obsahují úlohy, které by neměly být přerušeny iOSem, pokud by aplikace změnila stav. Jedním ze způsobů, jak tyto úlohy chránit před přerušením, je zaregistrovat je v iOSu jako dlouhotrvající úlohy. Tento vzor můžete použít kdekoli ve vaší aplikaci, kde nechcete, aby se úkol přerušoval, pokud by uživatel aplikaci umístil na pozadí. Skvělým kandidátem na tento model by byly úlohy, jako je odeslání registračních informací nového uživatele na váš server nebo ověření přihlašovacích údajů.

Následující fragment kódu ukazuje registraci úlohy, která se má spustit na pozadí:

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

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

UIApplication.SharedApplication.EndBackgroundTask(taskID);

Proces registrace spáruje úlohu s jedinečným identifikátorem taskIDa pak ji zabalí do párování BeginBackgroundTask a EndBackgroundTask volání. K vygenerování identifikátoru voláme metodu BeginBackgroundTask objektu UIApplication a pak spustíme dlouho běžící úlohu, obvykle v novém vlákně. Po dokončení úkolu zavoláme EndBackgroundTask a předáme stejný identifikátor. To je důležité, protože iOS ukončí aplikaci, pokud BeginBackgroundTask volání nemá odpovídající EndBackgroundTask.

Důležité

Úlohy bezpečné na pozadí můžou běžet buď na hlavním vlákně, nebo na vlákně na pozadí v závislosti na potřebách aplikace.

Provádění úkolů během DidEnterBackground

Kromě zajištění dlouhodobé bezpečnosti na pozadí úlohy je možné registraci použít k zahájení úloh, protože aplikace je umístěna na pozadí. iOS poskytuje metodu události ve třídě AppDelegate , DidEnterBackground která se dá použít k ukládání stavu aplikace, ukládání uživatelských dat a šifrování citlivého obsahu před vstupem aplikace na pozadí. Aplikace má přibližně pět sekund, než se vrátí z této metody, nebo se ukončí. Proto je možné volat úlohy čištění, které mohou trvat déle než pět sekund, z této DidEnterBackground metody. Tyto úlohy musí být vyvolány v samostatném vlákně.

Proces je téměř stejný jako registrace dlouhotrvající úlohy. Následující fragment kódu ukazuje tuto akci:

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

Začneme přepsáním DidEnterBackground metody v AppDelegate, kde zaregistrujeme náš úkol prostřednictvím BeginBackgroundTask , jak jsme to udělali v předchozím příkladu. Dále vytvoříme nové vlákno a provedeme dlouho běžící úlohu. Všimněte si, že EndBackgroundTask volání je nyní provedeno z dlouhotrvající úlohy, protože DidEnterBackground metoda již bude vrácena.

Důležité

iOS používá mechanismus watchdogu k zajištění toho, aby uživatelské rozhraní aplikace zůstalo responzivní. Aplikace, která tráví příliš mnoho času, DidEnterBackground přestane v uživatelském rozhraní reagovat. Spuštění úloh na pozadí umožňuje DidEnterBackground vrátit se včas, udržet uživatelské rozhraní responzivní a zabránit hlídacímu hlídacímu zařízení v zabíjení aplikace.

Zpracování časových limitů úloh na pozadí

iOS omezuje, jak dlouho může úloha na pozadí běžet, a pokud EndBackgroundTask volání není provedeno v přiděleném čase, aplikace se ukončí. Udržováním přehledu o zbývající době na pozadí a používáním obslužných rutin vypršení platnosti v případě potřeby se můžeme vyhnout ukončení aplikace v iOSu.

Přístup ke zbývajícímu času na pozadí

Pokud se aplikace s registrovanými úlohami přesune na pozadí, registrované úkoly se spustí přibližně 600 sekund. Pomocí statické BackgroundTimeRemaining vlastnosti UIApplication třídy můžeme zkontrolovat, kolik času musí úkol dokončit. Následující kód nám poskytne čas( v sekundách), který nám zbývá na pozadí:

double timeRemaining = UIApplication.SharedApplication.BackgroundTimeRemaining;

Zabránění ukončení aplikace s obslužnými rutinami vypršení platnosti

Kromě udělení přístupu k BackgroundTimeRemaining vlastnosti poskytuje iOS elegantní způsob, jak zpracovat vypršení platnosti času na pozadí prostřednictvím obslužné rutiny vypršení platnosti. Jedná se o volitelný blok kódu, který se spustí, když vyprší platnost času přiděleného úkolu. Kód ve volání EndBackgroundTask obslužné rutiny vypršení platnosti a předá ID úlohy, což značí, že aplikace funguje dobře a brání ukončení aplikace iOSem, i když úloha vyprší. EndBackgroundTask musí být volána v obslužné rutině vypršení platnosti, stejně jako v normálním průběhu provádění.

Obslužná rutina vypršení platnosti se vyjadřuje jako anonymní funkce pomocí výrazu lambda, jak je znázorněno níže:

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

Zatímco obslužné rutiny vypršení platnosti nejsou pro spuštění kódu nutné, měli byste vždy použít obslužnou rutinu vypršení platnosti s úlohou na pozadí.

Úlohy na pozadí v iOSu 7 a novějších

Největší změnou v iOSu 7 s ohledem na úlohy na pozadí není způsob implementace úloh, ale při jejich spuštění.

Vzpomeňte si, že před iOSem 7 měla úloha spuštěná na pozadí 600 sekund. Jedním z důvodů tohoto limitu je, že úloha spuštěná na pozadí by zařízení po dobu trvání úlohy zůstala vzhůru:

Graph of the task keeping the app awake pre-iOS 7

Zpracování na pozadí iOS 7 je optimalizované pro delší životnost baterie. V iOSu 7 se pozadí stává oportunistickým: místo toho, aby zařízení bylo vzhůru, úkoly respektují, když zařízení přejde do režimu spánku, a místo toho se jejich zpracování v blocích, když se zařízení probudí, aby zvládlo telefonní hovory, oznámení, příchozí e-maily a další běžná přerušení. Následující diagram poskytuje přehled o tom, jak může být úkol rozdělený:

Graph of the task being broken into chunks post-iOS 7

Vzhledem k tomu, že doba běhu úlohy není delší, musí se úlohy, které provádějí síťové přenosy, zpracovávat jinak v iOSu 7. Vývojářům se doporučuje používat NSURlSession rozhraní API ke zpracování síťových přenosů. V další části najdete přehled přenosů na pozadí.

Přenosy na pozadí

Základem přenosů na pozadí v iOSu 7 je nové NSURLSession rozhraní API. NSURLSession umožňuje nám vytvářet úkoly pro:

  1. Přenos obsahu přes přerušení sítě a zařízení
  2. Nahrání a stažení velkých souborů ( služba přenosu na pozadí ).

Pojďme se podrobněji podívat, jak to funguje.

NSURLSession API

NSURLSession je výkonné rozhraní API pro přenos obsahu přes síť. Poskytuje sadu nástrojů pro zpracování přenosu dat prostřednictvím přerušení sítě a změn ve stavech aplikací.

Rozhraní NSURLSession API vytvoří jednu nebo několik relací, které zase vytvářejí úlohy pro kyvadlovou dopravu bloků souvisejících dat v síti. Úlohy běží asynchronně pro rychlý a spolehlivý přenos dat. Vzhledem k tomu NSURLSession , že je asynchronní, každá relace vyžaduje blok obslužné rutiny dokončení, aby systém a aplikace věděly, kdy je přenos dokončen.

Pokud chcete provést přenos sítě, který je platný v systému pre-iOS 7 i po iOS 7, zkontrolujte, jestli NSURLSession je k dispozici pro zařazení přenosů do fronty, a pokud není, použijte běžnou úlohu na pozadí k provedení přenosu:

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

Důležité

Vyhněte se volání aktualizace uživatelského rozhraní z pozadí v kódu kompatibilním s iOSem 6, protože iOS 6 nepodporuje aktualizace uživatelského rozhraní na pozadí a ukončí aplikaci.

Rozhraní NSURLSession API obsahuje bohatou sadu funkcí pro zpracování ověřování, správu neúspěšných přenosů a hlášení chyb na straně klienta , ale ne na straně serveru. Pomáhá přemostění přerušení v době běhu úloh zavedené v iOSu 7 a také poskytuje podporu pro rychlé a spolehlivé přenosy velkých souborů. V další části se seznámíte s touto druhou funkcí.

Služba přenosu na pozadí

Před iOSem 7 nebylo nahrávání nebo stahování souborů na pozadí nespolehlivé. Úlohy na pozadí mají omezenou dobu, než se spustí, ale doba potřebnou k přenosu souboru se liší v síti a velikosti souboru. V iOSu 7 můžeme použít k úspěšnému NSURLSession nahrání a stažení velkých souborů. Konkrétní NSURLSession typ relace, který zpracovává síťové přenosy velkých souborů na pozadí, se označuje jako služba přenosu na pozadí.

Přenosy iniciované pomocí služby Přenos na pozadí se spravují operačním systémem a poskytují rozhraní API pro zpracování ověřování a chyb. Vzhledem k tomu, že přenosy nejsou vázány libovolným časovým limitem, lze je použít k nahrání nebo stažení velkých souborů, automatické aktualizace obsahu na pozadí a další. Podrobnosti o implementaci služby najdete v návodu k přenosu na pozadí.

Služba přenosu na pozadí je často spárovaná s funkcemi Background Fetch nebo Remote Notifications, které aplikacím pomáhají aktualizovat obsah na pozadí. V následujících dvou částech představíme koncept registrace celých aplikací, které se budou spouštět na pozadí v iOSu 6 i iOS 7.