Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Začínáme s
Programování pro iOS - 23. Jak se aktivovat, jsme-li v pozadí
5. ledna 2011, 00.00 | Známe už základy hry, kterou s námi iOS hraje a víme, jak si vyžádat trochu více času ve chvíli, kdy je aplikace odsunuta z obrazovky. Co ale v případě, kdy bychom ji potřebovali aktivovat o něco později?
V minulých dílech seriálu jsme se zabývali "multitaskingem" (ve skutečnosti jde spíše o sadu konvencí, pravidel a podmínek, za nichž systém aplikaci dovolí běžet na pozadí).
Restík od minula
V předchozím dílu jsme si ukázali kromě jiného chování aplikace, jež zablokuje hlavní vlákno a řekli jsme si, že v takové aplikaci poběží jak toto hlavní vlákno, tak i všechna vlákna ostatní, deset sekund po její deaktivaci – pak je násilně ukončena. Zmínili jsme se ale také o tom, že neběží časovač, aktivovaný kódem
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
...
[NSTimer scheduledTimerWithTimeInterval:.1
target:self selector:@selector(timer)
userInfo:nil repeats:YES];
...
return YES;
}
a slíbili jsme si, že pro ty čtenáře – existují-li vůbec tací –, již snad náhodou nevědí, proč tomu tak je, dnes uvedeme vysvětlení.
To je velmi prosté: časovače založené na službách třídy NSTimer a podobných (speciálně tedy také odložené odesílání zpráv, aktivované standardní metodou performSelector:withObject:afterDelay:, jež není ničím jiným, než pohodlným API nad NSTimerem) jsou založeny na event loopu. Timer nedělá nic jiného, než že si od správce event loopu vyžádá vložení události, jež nastane v předem definovaném čase.
Event loop je ovšem součástí hlavního vlákna* a běží v jeho rámci. Je-li hlavní vlákno blokováno, event loop tedy neběží, a časovače fungovat nemohou.
* Přesněji řečeno, každé vlákno má vlastní event loop; pokud bychom tedy NSTimer použili v jiném vláknu, např. takto:
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
[[[NSOperationQueue alloc] init] addOperationWithBlock:^{
[NSTimer scheduledTimerWithTimeInterval:.1
target:self selector:@selector(timer)
userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run]; //*
}];
return YES;
}
kde řádek označený hvězdičkou je nutný pro spuštění event loopu v druhém vláknu (systém sám se postará o spuštění event loopu samozřejmě jen v tom hlavním), poběží právě tehdy, pokud toto vlákno není blokované. To ale spíše jen pro úplnost; v praxi se časovače v jiném vláknu než v hlavním využívají jen zřídkakdy.
Lokální notifikace
Tzv. "lokální notifikace" jsou jediným způsobem, jak si může aplikace sama programově vyžádat, aby po případném suspendování byla probuzena v požadovaný čas. Není to samo o sobě nijak komplikované (ačkoli na řadu různých háčků narazíme později) – prostě jen v programu vytvoříme objekt třídy UILocalNotification, nastavíme požadovaný čas a případné další atributy. Typicky by to mohlo vypadat kupříkladu takto:
UILocalNotification *ln=[[[UILocalNotification alloc] init]
autorelease];
ln.fireDate=[NSDate dateWithTimeIntervalSinceNow:...];
ln.alertBody=@"Launch MyGreatApplication";
[[UIApplication sharedApplication] scheduleLocalNotification:ln];
Po uplynutí zadaného času... nastanou výše zmíněné komplikace. To proto, že systém interpretuje zadanou notifikaci různě za různých podmínek, a my ji proto také musíme různým způsobem v aplikaci ošetřit.
Aplikace je na popředí
Pokud náhodou zadaný čas vyprší ještě v době, kdy je aplikace aktivní a "má obrazovku", pošle se pouze aplikačnímu delegátu zpráva
-(void)application:(UIApplication*)application
didReceiveLocalNotification:(UILocalNotification*)notification;
jejímž argumentem je samozřejmě dříve vytvořený objekt třídy UILocalNotification. Pokud bychom tuto zprávu v aplikačním delegátu vůbec neimplementovali, nestane se nic, a o notifikaci se vůbec nedozvíme.
Jinak se nic neděje; chceme-li na notifikaci nějak reagovat, musíme to zajistit programově. V tomto případě se tedy lokální notifikace chová v zásadě stejně, jako NSTimer, a nic jiného nám nenabídne.
Aplikace běží nebo je suspendována v pozadí
Toto je hlavní situace, pro niž jsme vůbec k notifikaci sáhli: pokud aplikace buď běží na pozadí, nebo je suspendována, systém umožňuje ji na základě notifikace opět aktivovat (což jinak není možné: i pokud aplikace na pozadí běží, sama se programově aktivovat nemůže).
Ale... není to tak jednoduché.
Operační systém iOS je totiž sestaven na základě ne vždy zcela šťastné (a obecně nesplnitelné, samozřejmě) představy "aplikace, která není v popředí, nemůže udělat nic, o čem by uživatel nevěděl". Důsledkem tohoto přístupu je, že ve chvíli, kdy čas lokální notifikace vyprší, systém zobrazí alert s textem, který jsme při sestavení notifikace uložili do jejího atributu alertBody a s tlačítky "Close" a "View" (obsah toho druhého můžeme, chceme-li, změnit pomocí atributu alertAction).
Pokud uživatel zvolí "Close", naše aplikace zůstane suspendována a o ničem se ani nedozví.
Pokud uživatel zvolí "View" (nebo text, který jsme uložili do atributu alertAction), teprve systém naši aplikaci probudí. Pokud jsme implementovali v delegátu aplikace metodu application:didReceiveLocalNotification:, dostane odpovídající zprávu, jejímž argumentem bude patřičný objekt třídy UILocalNotification, po zprávě applicationDidBecomeActive:.
A co se stane, pokud ponecháme atribut alertBody prázdný?
Nic. Žádný alert se nezobrazí, takže uživatel nemůže stisknout tlačítko "View", a naše aplikace nebude aktivována.
Zde je ještě speciální možnost nastavit atribut applicationIconBadgeNumber na nějaké číslo; v takovém případě se přec jen něco málo stane – aplikační ikona bude opatřena tímto číslem v červeném kroužku – podobně jako např. počet zpráv v aplikaci Mail (takže lze předpokládat, že uživatel asi dříve nebo později aplikaci aktivuje, aby se podíval, co to má znamenat). Automatická aktivace ale nenastane ani v tomto případě.
Aplikace neběží
Poslední situace, již musíme speciálně ošetřit, je, pokud naše aplikace v době, kdy dojde k aktivaci lokální notifikace, vůbec neběží.
Operační systém iOS je naštěstí dostatečně chytrý k tomu, aby zobrazil stejný alert (nebo opatřil aplikační ikonu stejným číslem), a v případě, kdy po zobrazení alertu uživatel zvolí zvolí "View" (nebo text, který jsme uložili do atributu alertAction), systém naši aplikaci spustí. To je podstatné, protože naše aplikace mohla být v suspendovaném stavu kdykoli bez našeho vědomí ukončena, pokud systém potřeboval více paměti.
Drobný podraz, který musíme ošetřit, však spočívá v tom, že v tomto případě nedostaneme zprávu application:didReceiveLocalNotification:; namísto toho je notifikace uložena v argumentu launchOptions standardní zprávy application:didFinishLaunchingWithOptions: pod klíčem UIApplicationLaunchOptionsLocalNotificationKey.
Obsah seriálu (více o seriálu):
- Nastal čas na kakao...
- Tak nejdřív kakao ochutnáme...
- Programovací jazyk C: velmi, velmi stručně
- Objective C: to si vysvětlíme podrobněji
- Co jsme si o Objective C ještě neřekli...
- Nastal čas na kakao - Vznik a zánik objektů
- Nastal čas na kakao - Kopírování objektů
- Nastal čas na kakao - Skryté podtřídy
- Nastal čas na kakao - Základní služby objektů
- Nastal čas na kakao - Jak správně psát v Objective C
- Nastal čas na kakao - Jak správně importovat
- Nastal čas na kakao - Podtřídy, delegáti, vkládání, jak se to rýmuje?
- Nastal čas na kakao - Využití kategorií namísto dědičnosti
- Nastal čas na kakao - Vkládání objektů a přesměrování zpráv
- Nastal čas na kakao - Inicializace a rušení objektů
- Nastal čas na kakao - Metody initWith... a designovaný inicializátor
- Nastal čas na kakao - Inicializace: tipy a triky
- Nastal čas na kakao - Accesory: přístup k proměnným instancí
- Nastal čas na kakao - Šedá je teorie, zelený je strom života...
- Nastal čas na kakao - Více o XCode: inspektory
- Nastal čas na kakao - Aplikace RSS2: datový model
- Nastal čas na kakao - Aplikace RSS: implementace datového modelu
- Nastal čas na kakao - Aplikace RSS: parsování XML
- Nastal čas na kakao - Interface Builder a uživatelské rozhraní
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Druhý kontrolér a dokončení aplikace
- Nastal čas na kakao - Drobná vylepšení a zdokonalení...
- Nastal čas na kakao - Ladění
- Nastal čas na kakao - Třídy Foundation Kitu
- Nastal čas na kakao - Třídy Foundation Kitu (2)
- Nastal čas na kakao - Textové řetězce: NS(Mutable)String
- Nastal čas na kakao - Čísla, binární data a další...
- Nastal čas na kakao - Archivace objektů
- Nastal čas na kakao - Trocha magie, aneb distribuované objekty
- Nastal čas na kakao - Málem bychom zapomněli: NSAutoreleasePool
- Nastal čas na kakao - Zpracování výjimek: NSException
- Nastal čas na kakao - NSInvocation a černá magie
- Nastal čas na kakao - Kakao v Tygrovi
- Nastal čas na kakao - Notifikace: nepřímé předávání zpráv
- Nastal čas na kakao - NSUserDefaults
- Nastal čas na kakao - Co nového ve Foundation Kitu
- Nastal čas na kakao – s Intelem, s Intelem, jedeme do...
- Co nového v Xcode
- Začínáme s AppKitem
- Jak MVC v Kakau vypadá doopravdy?
- Jak MVC v Kakau vypadá doopravdy: dokončení
- Přehled tříd AppKitu
- Nastal čas na kakao - Přehled tříd AppKitu 2
- Přehled tříd AppKitu 3: zbývající třídy GUI
- Přehled tříd AppKitu 4: textový systém
- Nastal čas na kakao - Přehled tříd AppKitu 5: hlavně grafika
- Přehled tříd AppKitu 6: dokumentový systém
- Přehled tříd AppKitu 7: dokončení
- Pojmenované vlastnosti objektů
- Pojmenované vlastnosti objektů: implementace
- Pojmenované vlastnosti objektů: relace 1:N
- Pojmenované vlastnosti objektů: řazení jmen a agregační funkce
- Sledování změn objektů
- Sledování změn objektů – ukázka
- Sledování změn objektů – zdrojový kód
- Sledování změn objektů: kód modelu
- Sledování změn objektů: přímý přístup
- Kontroléry a vazby
- Vázání vazeb
- Další vazby s jednoduchým kontrolérem
- Implementace a použití převodu hodnot
- Validace hodnot
- Validace a chyby, a jedna hezká vazba...
- Práce s polem objektů
- Základní vazby NSArrayControlleru
- Převodníky, přepínače, placeholdery
- Mírná vylepšení v mezích zákona
- Objective C 2.0 - novinky z Leoparda
- NSTreeController
- Programování v Cocoa - Pár tipů a triků
- Programování v Cocoa - Základy kreslení
- Kterak nakreslit modrý obdélník...
- Další služby pro kreslení
- Obrázky a písmenka...
- Události a myš
- Lepší práce s myší
- Události klávesnice
- Input Management
- Příkazy a schránka
- Další události
- Táhni a padni
- Byli jsme na tahu; nyní padneme.
- Zvolme si, jak vhodit
- Drobnosti a chybičky
- Speciální případy tahání či házení
- Kterak táhnout něco, co neexistuje?
- Jak na sítě...
- NSURLConnection
- Safari za minutu
- Služby WebKitu
- Kakao v Leopardu
- Druhé Objective C
- Druhé Objective C: různé drobnosti
- Druhé Objective C: kategorie a protokoly
- Druhé Objective C: nový příkaz cyklu
- Druhé Objective C: atributy a accesory
- Druhé Objective C: atributy a accesory
- 64 je dvakrát 32
- Ubicumque dulce est, ibi et acidum invenies...
- Irbis: že prý žádné novinky?
- Blok sem, blok tam, nám už je to všechno jasné...
- Bloky jsou i v AppKitu
- Irbis a Foundation Kit
- Kde jsou má data?
- Kde jsou má data? V NSCache!
- Soubor, jméno, URL, jak se to rýmuje...
- Další podpora NSURL
- Zabíjení!
- A máme tady i...OS!
- Systémové prvky GUI
- Programování pro iOS 1. díl - Rozdíly mezi "i" a "Mac"
- Programování pro iOS - 2. Začínáme programovat
- Programování pro iOS - 3. základní ovladače a propojení GUI s kódem
- Programování pro iOS - 4. Varovná hlášení
- Programování pro iOS - 5. Rámce a jejich řídicí objekty
- Programování pro iOS - 6. Ukládání dat
- Programování pro iOS - 7. Správa paměti a starý restík
- Programování pro iOS - 8. Dokončení aplikace
- Programování pro iOS - 9. Jak dostat aplikaci do iPhone
- Programování pro iOS - 10. Instalace aplikace do cizího iPhone
- Programování pro iOS - 11. Jak dostat aplikaci do libovolného iPhone
- Programování pro iOS - 12. Touching!
- Programování pro iOS - 13. Kreslíme na iPhone
- Programování pro iOS - 14. Udělejme gesto
- Programování pro iOS - 15. Další gesta
- Programování pro iOS - 16. Více prstů, více zábavy
- Programování pro iOS - 17. Podpora standardních gest
- Programování pro iOS - 18. Recognizery v iOS
- Programování pro iOS - 19. Další standardní recognizery
- Programování pro iOS - 20. Co nového v iOSu
- Programování pro iOS - 21. "Multitasking"
- Programování pro iOS - 22. Nulla est honesta avaritia nisi temporis
- Programování pro iOS - 23. Jak se aktivovat, jsme-li v pozadí
- Programování pro iOS - 24. Zbývající drobnosti
- Programování pro iOS - 25. Řídicí objekty rámců
- Programování pro iOS - 26. Jak se dělá UIViewController
- Programování pro iOS - 27. Kde vzít rámce
- Programování pro iOS - 28. Základní služby
- Programování pro iOS - 29. Práce s rámci
- Programování pro iOS - 30. Rotace zařízení
- Programování pro iOS - 31. Správa paměti v rámcích
- Programování pro iOS - 32. Řídicí objekt pro tabulky
- Programování pro iOS - 33. Řídicí objekt pro strom
- Programování pro iOS - 33. Více o UINavigationControlleru
- Programování pro iOS - 35. Ještě jednou UINavigationController
- Programování pro iOS - 36. Po navigátoru taby
- Programování pro iOS - 37. Více o UITabBarControlleru
- Programování pro iOS - 38. Dokončení UITabBarControlleru
- Programování pro iOS - 39. UIPopoverController
- Programování pro iOS - 40. Další triky UIPopoverControlleru
- Programování pro iOS - 41. Zbývající služby UIPopoverControlleru
- Programování pro iOS - 42. UISplitViewController
- Programujeme v
iTunesXcode 4 - Programování pro iOS - 44. Předvolby Xcode 4
- Programování pro iOS - 45. Práce v Xcode 4
- Xcode 4: projekt a cíle
- Xcode 4: práce s cíli
- Xcode 4: Build Settings
- Xcode 4: Build Phases
- Xcode4: Build Phases podruhé
- Xcode 4: Co jsou to Build Rules?
- Xcode4: taje editoru
- Xcode4: automatické doplňování v editoru
- XIBy chyby
- Více o XIBech
- Editor XIBů
- Inspektory pro XIBy
- Vazby mezi objekty v XIBech
- Vazby mezi objekty v kódu
- Paletky Xcode pro XIBy
- Xcode 4: levý sloupec
- Xcode 4: okno Organizer
- Xcode 4: okno Organizer, část druhá
- Xcode 4: co je to Workspace?
- Xcode 4: základy schémat
- Xcode 4: akční schémata