objc.io

Před iOS 7 byli vývojáři docela omezeni v tom, co mohli dělat, když jejich aplikace opustily popředí. Kromě funkcí založených na VOIP a poloze byl jediným způsobem, jak spustit kód na pozadí, použití úloh na pozadí, omezených na několik minut. Pokud jste chtěli stáhnout velké video pro offline prohlížení nebo zálohovat fotografie uživatele na server, mohli byste dokončit pouze část práce.

iOS 7 přidává dvě nová rozhraní API pro aktualizaci uživatelského rozhraní a obsahu vaší aplikace na pozadí. První, načtení na pozadí, Umožňuje v pravidelných intervalech načíst nový obsah ze sítě. Druhá, vzdálená oznámení, je nová funkce využívající Push oznámení k upozornění aplikace, když došlo k události. Oba tyto nové mechanismy vám pomohou udržovat rozhraní aplikace aktuální a mohou naplánovat práci na nové službě přenosu na pozadí,která vám umožní provádět síťové přenosy mimo proces (stahování a nahrávání).

načítání na pozadí a vzdálená oznámení jsou jednoduché háčky delegátů aplikací s 30 sekundami času na nástěnné hodiny k provedení práce před pozastavením aplikace. Nejsou určeny pro CPU intenzivní práci nebo dlouhotrvající úkoly, spíše, jsou pro fronty až dlouhotrvající požadavky na sítě, jako je velký film ke stažení, nebo provádění rychlých aktualizací obsahu.

z pohledu uživatele je jedinou zjevnou změnou multitaskingu nový přepínač aplikací, který zobrazuje snímek uživatelského rozhraní každé aplikace tak, jak to bylo, když opustil popředí. Existuje však důvod pro zobrazení snímků – nyní můžete aktualizovat snímek aplikace po dokončení práce na pozadí a zobrazit náhled nového obsahu. Aplikace pro sociální sítě, zprávy nebo počasí nyní mohou zobrazovat nejnovější obsah, aniž by uživatel musel aplikaci otevírat. Uvidíme, jak aktualizovat snímek později.

background Fetch

Background Fetch je druh inteligentního dotazovacího mechanismu, který funguje nejlépe pro aplikace, které mají časté aktualizace obsahu, jako jsou sociální sítě, zprávy nebo aplikace pro počasí. Systém probudí aplikaci na základě chování uživatele, a jeho cílem je spustit načítání pozadí před spuštěním aplikace uživatelem. Pokud například uživatel vždy používá aplikaci v 1: 00, systém se učí a přizpůsobuje a provádí načítání před obdobím používání. Načítání pozadí je spojeno mezi aplikacemi rádiem zařízení, aby se snížilo využití baterie, a pokud nahlásíte, že nová data nebyla během načítání k dispozici, iOS se může přizpůsobit, pomocí těchto informací se vyhnout načítání v tichých časech.

prvním krokem k povolení načtení na pozadí je určit, že tuto funkci použijete v klíči UIBackgroundModes v informačním seznamu. Nejjednodušší způsob, jak toho dosáhnout, je použít kartu nové možnosti v editoru projektu Xcode 5, který obsahuje sekci režimy pozadí pro snadnou konfiguraci možností multitaskingu.

Případně můžete klíč upravit ručně:

<key>UIBackgroundModes</key><array> <string>fetch</string></array>

dále řekněte iOS, jak často chcete načíst:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ ; return YES;}

výchozí interval načtení není nikdy, takže budete muset nastavit časový interval nebo aplikace nebude nikdy volána na pozadí. Hodnota UIApplicationBackgroundFetchIntervalMinimum požádá systém, aby spravoval, když se vaše aplikace probudí, tak často, jak je to možné, ale pokud je to zbytečné, měli byste zadat svůj vlastní časový interval. Například aplikace počasí může aktualizovat podmínky pouze každou hodinu. iOS bude čekat alespoň zadaný časový interval mezi načtením pozadí.

pokud vaše aplikace umožňuje uživateli odhlásit se a víte, že nebudou žádná nová data, možná budete chtít nastavit minimumBackgroundFetchInterval zpět na UIApplicationBackgroundFetchIntervalNever, abyste byli dobrým občanem a šetřili zdroje.

posledním krokem je implementace následující metody do delegáta aplikace:

- (void) application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSURLSessionConfiguration *sessionConfiguration = ; NSURLSession *session = ; NSURL *url = initWithString:@"http://yourserver.com/data.json"]; NSURLSessionDataTask *task = ; // Start the task ;}

zde můžete provádět práci, když vás systém probudí. Nezapomeňte, že máte pouze 30 sekund, abyste zjistili, zda je nový obsah k dispozici, zpracovat nový obsah a aktualizovat uživatelské rozhraní. To by mělo být dost času na načtení dat ze sítě a načtení několika miniatur pro vaše uživatelské rozhraní, ale ne mnohem víc. Po dokončení požadavků na síť a aktualizaci uživatelského rozhraní byste měli zavolat obslužnou rutinu dokončení.

popisovač dokončení slouží dvěma účelům. Za prvé, systém měří sílu používanou vaším procesem a zaznamenává, zda byla nová data k dispozici na základě argumentu UIBackgroundFetchResult, který jste předali. Za druhé, když zavoláte obslužný program dokončení, pořídí se snímek uživatelského rozhraní a aktualizuje se přepínač aplikací. Uživatel uvidí nový obsah, když přepíná aplikace. Toto chování snapshotting popisovače dokončení je společné pro všechny obslužné rutiny dokončení v nových multitaskingových API.

V aplikaci v reálném světě byste měli předat completionHandler dílčím komponentám aplikace a zavolat ji, když zpracováváte data a aktualizujete své uživatelské rozhraní.

V tomto okamžiku se možná divíte, jak může iOS snímat uživatelské rozhraní aplikace, když je spuštěno na pozadí, a jak životní cyklus aplikace pracuje s načtením na pozadí. Pokud je vaše aplikace aktuálně pozastavena, systém ji probudí před voláním application: performFetchWithCompletionHandler:. Pokud vaše aplikace není spuštěna, systém ji spustí a zavolá obvyklé metody delegáta, včetně application: didFinishLaunchingWithOptions:. Můžete si to představit jako aplikaci běžící přesně stejným způsobem, jako by ji uživatel spustil z odrazového můstku, kromě uživatelského rozhraní je neviditelné, vykreslené mimo obrazovku.

ve většině případů budete provádět stejnou práci, když se aplikace spustí na pozadí jako v popředí, ale spuštění pozadí můžete zjistit při pohledu na vlastnost applicationState uiapplication:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ NSLog(@"Launched in background %d", UIApplicationStateBackground == application.applicationState); return YES;}

testování načtení pozadí

existují dva způsoby, jak simulovat načtení pozadí. Nejjednodušší metodou je spustit aplikaci z Xcode a kliknout na tlačítko simulovat načtení pozadí v nabídce ladění Xcode, když je aplikace spuštěna.

Alternativně můžete použít schéma pro změnu způsobu spuštění aplikace Xcode. Pod položkou nabídky Xcode produkt vyberte schéma a poté spravovat schémata. Odtud upravte nebo přidejte nové schéma a zaškrtněte políčko Spustit kvůli události načtení na pozadí, jak je uvedeno níže.

vzdálená oznámení

vzdálená oznámení vám umožní upozornit vaši aplikaci, když dojde k důležitým událostem. Možná budete mít nové rychlé zprávy, které chcete doručit, nejnovější zprávy, které chcete odeslat, nebo nejnovější epizodu oblíbeného televizního pořadu vašeho uživatele, který je připraven ke stažení pro offline prohlížení. Vzdálená oznámení jsou skvělá pro sporadický, ale okamžitě důležitý obsah, kde zpoždění mezi načtením pozadí nemusí být přijatelné. Vzdálená oznámení mohou být také mnohem efektivnější než načtení na pozadí, protože aplikace se spustí pouze v případě potřeby.

vzdálené oznámení je opravdu jen normální oznámení Push s nastaveným příznakem content-available. Můžete poslat push s varovnou zprávou informující uživatele, že se něco stalo, zatímco aktualizujete uživatelské rozhraní na pozadí. Vzdálená oznámení však mohou být také tichá, neobsahují žádnou varovnou zprávu ani zvuk, používají se pouze k aktualizaci rozhraní aplikace nebo ke spuštění práce na pozadí. Po dokončení stahování nebo zpracování nového obsahu můžete odeslat místní oznámení.

Tichá oznámení push jsou omezena rychlostí, takže se nebojte posílat tolik, kolik vaše aplikace potřebuje. servery iOS a APNS budou kontrolovat, jak často jsou doručovány, a nebudete mít problémy s odesíláním příliš mnoha. Pokud jsou vaše oznámení push škrtena, mohou být zpožděna až do příštího odeslání paketu keep-alive nebo přijetí jiného oznámení.

odesílání vzdálených oznámení

Chcete-li odeslat vzdálené oznámení, Nastavte příznak dostupný pro obsah v užitečném zatížení oznámení push. Příznak dostupný pro obsah je stejný klíč, který se používá k upozornění aplikací pro novinový stánek, takže většina push skriptů a knihoven již podporuje vzdálená oznámení. Když posíláte vzdálené oznámení, můžete také chtít zahrnout některá data do užitečného zatížení oznámení, aby vaše aplikace mohla odkazovat na událost. To vám může ušetřit několik požadavků na sítě a zvýšit citlivost vaší aplikace.

doporučuji používat Houston nástroj Nomad CLI k odesílání zpráv push při vývoji, ale můžete použít svou oblíbenou knihovnu nebo skript.

Houston můžete nainstalovat jako součást drahokamu nomad-cli ruby:

gem install nomad-cli

a poté odešlete oznámení pomocí nástroje apn zahrnutého v Nomad

# Send a Push Notification to your Deviceapn push <device token> -c /path/to/key-cert.pem -n -d content-id=42

zde příznak -n určuje, že by měl být zahrnut klíč dostupný pro obsah a -d nám umožňuje přidat vlastní datové klíče do užitečného zatížení.

výsledné notifikační zatížení vypadá takto:

{ "aps" : { "content-available" : 1 }, "content-id" : 42}

iOS 7 přidává novou metodu delegáta aplikace, která se volá, když je přijato oznámení push s klíčem dostupným pro obsah:

- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSLog(@"Remote Notification userInfo is %@", userInfo); NSNumber *contentID = userInfo; // Do something with the content ID completionHandler(UIBackgroundFetchResultNewData);}

Opět platí, že aplikace je spuštěn na pozadí a vzhledem k tomu, 30 sekund načíst nový obsah a aktualizovat své uživatelské rozhraní, před voláním obslužného programu dokončení. Mohli bychom provést rychlý požadavek na síť, jako jsme to udělali v příkladu načtení na pozadí, ale použijme novou výkonnou službu přenosu na pozadí k zadání velkého úkolu stahování a uvidíme, jak můžeme aktualizovat naše uživatelské rozhraní Po dokončení.

NSURLSession and Background Transfer Service

zatímco NSURLSession je nová třída v systému iOS 7, odkazuje také na novou technologii v základových sítích. Určené k nahrazení NSURLConnection jsou zachovány známé pojmy a třídy jako NSURL, NSURLRequest a NSURLResponse. Budete pracovat s náhradou NSURLConnection, NSURLSessionTask, aby síťové požadavky a zpracovat jejich odpovědi. Existují tři typy úloh relace-data, stahování a nahrávání – z nichž každá přidává syntaktický cukr do NSURLSessionTask, takže byste měli použít vhodný pro případ použití.

An NSURLSession koordinuje jeden nebo více z těchto NSURLSessionTask s a chová se podle NSURLSessionConfiguration, se kterým byl vytvořen. Můžete vytvořit více NSURLSessions pro seskupení souvisejících úkolů se stejnou konfigurací. Chcete-li komunikovat se službou přenosu pozadí, vytvoříte konfiguraci relace pomocí . Úkoly přidané do relace na pozadí jsou spuštěny v externím procesu a pokračují, i když je vaše aplikace pozastavena, havaruje nebo je zabita.

NSURLSessionConfiguration umožňuje nastavit výchozí záhlaví HTTP, konfigurovat zásady mezipaměti, omezit používání celulární sítě a další. Jednou z možností je příznak discretionary, který umožňuje systému naplánovat úkoly pro optimální výkon. To znamená, že vaše přenosy přejdou přes Wifi pouze tehdy, když má zařízení dostatečný výkon. Pokud je baterie vybitá nebo je k dispozici pouze mobilní připojení, váš úkol se nespustí. Příznak discretionary má účinek pouze v případě, že objekt konfigurace relace byl vytvořen voláním metody backgroundSessionConfiguration: a pokud je přenos pozadí zahájen, když je vaše aplikace v popředí. Pokud je přenos zahájen z pozadí, přenos bude vždy spuštěn v režimu volného uvážení.

nyní víme něco o NSURLSession a o tom, jak funguje relace na pozadí, vraťme se k našemu příkladu vzdáleného oznámení a přidejte nějaký kód, abyste si mohli stáhnout službu přenosu na pozadí. Po dokončení stahování upozorníme uživatele, že soubor je k dispozici pro použití.

NSURLSessionDownloadTask

nejprve se postaráme o vzdálené oznámení a požádáme o NSURLSessionDownloadTask o službě přenosu na pozadí. V backgroundURLSession vytvoříme NURLSession s konfigurací relace na pozadí a přidáme delegáta naší aplikace jako delegáta relace. Dokumentace nedoporučuje vytvářet instanci více relací se stejným identifikátorem, proto používáme dispatch_once, abychom se vyhnuli možným problémům:

- (NSURLSession *)backgroundURLSession{ static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSString *identifier = @"io.objc.backgroundTransferExample"; NSURLSessionConfiguration* sessionConfig = ; session = ]; }); return session;}- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSLog(@"Received remote notification with userInfo %@", userInfo); NSNumber *contentID = userInfo; NSString *downloadURLString = ]; NSURL* downloadURL = ; NSURLRequest *request = ; NSURLSessionDownloadTask *task = downloadTaskWithRequest:request]; task.taskDescription = ]; ; completionHandler(UIBackgroundFetchResultNewData);}

vytvoříme úlohu stahování pomocí metody třídy NSURLSession a nakonfigurujeme její požadavek a poskytneme popis pro pozdější použití. Nezapomeňte zavolat , abyste skutečně spustili úlohu, protože všechny úkoly relace začínají v pozastaveném stavu.

nyní musíme implementovat metody NSURLSessionDownloadDelegate, abychom mohli přijímat zpětná volání po dokončení stahování. Možná budete muset implementovat metody NSURLSessionDelegate nebo NSURLSessionTaskDelegate, pokud potřebujete zpracovat autentizaci nebo jiné události v životním cyklu relace. Měli byste konzultovat životní cyklus dokumentu Apple relace URL s vlastními delegáty, což vysvětluje celý životní cyklus všech typů úkolů relace.

žádná z delegátových metod NSURLSessionDownloadDelegate není volitelná, ale jediná, kde musíme v tomto příkladu podniknout kroky, je . Po dokončení stahování úlohy budete mít k dispozici dočasnou adresu URL souboru na disku. Soubor musíte přesunout nebo zkopírovat do úložiště aplikace, protože po návratu z této metody delegáta bude odstraněn z dočasného úložiště.

#Pragma Mark - NSURLSessionDownloadDelegate- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ NSLog(@"downloadTask:%@ didFinishDownloadingToURL:%@", downloadTask.taskDescription, location); // Copy file to your app's storage with NSFileManager // ... // Notify your UI}- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{}- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{}

pokud vaše aplikace stále běží v popředí po dokončení úlohy relace na pozadí, bude výše uvedený kód postačující. Ve většině případů však vaše aplikace nebude spuštěna nebo bude pozastavena na pozadí. V těchto případech musíte implementovat dvě metody delegátů aplikací, aby systém mohl vaši aplikaci probudit. Na rozdíl od předchozích zpětných volání delegátů je delegát aplikace volán dvakrát, protože delegáti relace a úkolu mohou obdržet několik zpráv. Metoda delegáta aplikace application: handleEventsForBackgroundURLSession: je volána před odesláním těchto NSURLSession delegátových zpráv a URLSessionDidFinishEventsForBackgroundURLSession je volána později. V první metodě uložíte pozadí completionHandler a v druhé ji zavoláte k aktualizaci uživatelského rozhraní:

- (void) application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{ // You must re-establish a reference to the background session, // or NSURLSessionDownloadDelegate and NSURLSessionDelegate methods will not be called // as no delegate is attached to the session. See backgroundURLSession above. NSURLSession *backgroundSession = ; NSLog(@"Rejoining session with identifier %@ %@", identifier, backgroundSession); // Store the completion handler to update your UI after processing session events ;}- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{ NSLog(@"Background URL session %@ finished events.\n", session); if (session.configuration.identifier) { // Call the handler we stored in -application:handleEventsForBackgroundURLSession: ; }}- (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString *)identifier{ if () { NSLog(@"Error: Got multiple handlers for a single session identifier. This should not happen.\n"); } ;}- (void)callCompletionHandlerForSession: (NSString *)identifier{ CompletionHandlerType handler = ; if (handler) { ; NSLog(@"Calling completion handler for session %@", identifier); handler(); }}

tento dvoustupňový proces je nezbytný k aktualizaci uživatelského rozhraní aplikace, pokud ještě nejste v popředí po dokončení přenosu na pozadí. Navíc, pokud aplikace není spuštěna vůbec po dokončení přenosu na pozadí, iOS ji spustí na pozadí a předchozí metody delegování aplikací a relací jsou volány po application:didFinishLaunchingWithOptions:.

konfigurace a omezení

krátce jsme se dotkli výkonu přenosů na pozadí, ale měli byste prozkoumat dokumentaci a podívat se na možnosti NSURLSessionConfiguration, které nejlépe podporují váš případ použití. Například NSURLSessionTasks podporuje časové limity zdrojů prostřednictvím vlastnosti NSURLSessionConfigurationtimeoutIntervalForResource. Můžete to použít k určení, jak dlouho chcete povolit dokončení převodu, než se úplně vzdáte. Můžete to použít, pokud je váš obsah k dispozici pouze po omezenou dobu, nebo pokud selhání stažení nebo nahrání zdroje v daném timeInterval naznačuje, že uživatel nemá dostatečnou šířku pásma Wifi.

kromě úkolů stahování NSURLSession plně podporuje úkoly nahrávání, takže můžete nahrát video na váš server na pozadí a ujistit uživatele, že již nemusí opustit aplikaci spuštěnou, jak by to mohlo být provedeno v systému iOS 6. Příjemným dotykem by bylo nastavit vlastnost sessionSendsLaunchEvents vašeho NSURLSessionConfiguration na NO, pokud vaše aplikace po dokončení přenosu nepotřebuje spuštění na pozadí. Efektivní využití systémových prostředků udržuje iOS i uživatele šťastným.

konečně existuje několik omezení při používání relací na pozadí. Protože je vyžadován delegát, nemůžete použít jednoduché blokové metody zpětného volání na NSURLSession. Spuštění aplikace na pozadí je relativně drahé, takže přesměrování HTTP jsou vždy přijímána. Služba přenosu na pozadí podporuje pouze HTTP a HTTPS a nemůžete používat vlastní protokoly. Systém optimalizuje převody na základě dostupných zdrojů a nemůžete svůj přenos neustále nutit k pokroku na pozadí.

také si všimněte, že NSURLSessionDataTasks nejsou podporovány v relacích na pozadí vůbec a tyto úkoly byste měli používat pouze pro krátkodobé, malé požadavky, nikoli pro stahování nebo nahrávání.

shrnutí

výkonné nové multitaskingové a síťové rozhraní API v systému iOS 7 otevírají celou řadu možností pro nové i stávající aplikace. Vezměme si případy použití ve vaší aplikaci, které mohou těžit z out-of-process síťových přenosů a čerstvých dat, a aby co nejvíce z těchto fantastických nových API. Obecně implementujte přenosy na pozadí, jako by vaše aplikace běžela v popředí, prováděla příslušné aktualizace uživatelského rozhraní a většina práce je již pro vás hotová.

  • použijte vhodné nové API pro obsah vaší aplikace.

  • být efektivní, a volání dokončení manipulátory co nejdříve.

  • obsluha dokončení aktualizuje snímek uživatelského rozhraní vaší aplikace.

další čtení

  • WWDC 2013 session „co je nového s multitaskingem“

  • WWDC 2013 session „co je nového v nadačních sítích“

  • průvodce programováním systému načítání URL

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.