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:
Software
Programování pro iOS - 28. Základní služby
9. února 2011, 00.00 | Už umíme vytvářet řídicí objekty rámců a jimi spravované rámce. Dnes se podíváme na základní služby, jež nám tyto objekty nabízejí. Začneme vzájmeným překrýváním obrazovek.
První a základní "obrazovku" – tedy samozřejmě stejně velký rámec, obsahující nějaké prvky grafického uživatelského rozhraní, a spravovaný nějakou podtřídou UIViewControlleru – standardně aktivuje delegát aplikace v metodě application:didFinishLaunchingWithOptions:; odpovídající kód je obvykle vygenerován z projektového vzoru Xcode a vypadá zhruba nějak takto:
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
Jak ale tuto obrazovku nahradíme jinou, spravovanou odlišným řídicím objektem?
Ačkoli v principu by bylo možné přidávat (nebo zaměňovat) vnořené rámce v okně přímo dalšími příkazy addSubview:, bylo by to velmi komplikované a navíc bychom se museli o všechny odpovídající efekty postarat ručně. Řídicí objekty rámců však nabízejí služby, jež požadovanou funkci zajistí snadno a velmi pohodlně.
Za běžných okolností se v iOSu setkáváme s třemi základními mechanismy vzájemného přepínání "obrazovek":
• "navigační struktura", v níž se zprava objevují nové "obrazovky" a doleva se vracíme ke starším; standardně je doprovázena lištou u horního okraje obrazovky s tlačítkem "zpět" specifického tvaru;
• "tab-bar", kde máme k dispozici několik "obrazovek", mezi nimiž přepínáme pomocí ikon při dolním okraji;
• nejobecnější struktura modálního překrývání, kde můžeme kdykoli aktuální obrazovku překrýt jakoukoli jinou a opět se vrátit k té původní.
Zpráva presentModalViewController:animated:
Prvé dvě složitější služby jsou realizovány pomocí speciálních řídicích objektů a ukážeme si je později. Třetí je nejjednodušší a je k dispozici v libovolném dědici třídy UIViewController; stačí poslat mu zprávu
-(void)presentModalViewController:(UIViewController*)mvc
animated:(BOOL)animated;
kde argument mvc je libovolný jiný UIViewController. Knihovní kód se pak automaticky postará o to, aby se rámce, jež patří řídicímu objektu mvc, umístily na obrazovku, kde překryjí stávající rámce příjemce zprávy.
Zároveň je možné si pomocí přepínače animated vyžádat, aby se nové rámce na obrazovce objevily pomocí některé ze standardních animací podporovaných systémem iOS. Standardní animací pro tento případ je "vyjetí zdola"; alternativně máme k dispozici animace
• UIModalTransitionStyleFlipHorizontal – "přetočení" rámce, běžně používané po stisknutí tlačítka (i) v pravém dolním rohu;
• UIModalTransitionStyleCrossDissolve – animace ve stylu "filmové prolínačky";
• UIModalTransitionStylePartialCurl – starý rámec se "odloupne", a ponechá na obrazovce obsah nového, částečně překrytý v horní části starým – jde o týž efekt, který používá např. standardní aplikace Maps, klepneme-li v ní na ikonku v pravém dolním rohu;
• pro úplnost, standardní animace "zdola nahoru" se jmenuje UIModalTransitionStyleCoverVertical.
Pro určení požadované animace použijeme atribut modalTransitionStyle nového řídicího objektu. Pokud bychom tedy chtěli např. zobrazit rámce spravované řídicím objektem foo pomocí "přetočené" animace, použijeme ve výchozím řídicím objektu (který tedy obsahuje mj. také instanční proměnnou foo) zhruba takovouto implementaci:
-(IBAction)flipToTheOtherView:sender {
foo.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:foo animated:YES];
}
Samozřejmě, že – v závislosti na konkrétní struktuře naší aplikace – nemusíme "překryvný" řídicí objekt a jeho rámce udržovat v paměti pořád; naopak, mnohdy je vhodnější je vytvořit cíleně právě až ve chvíli, kdy jsou zapotřebí, nějak takto:
-(IBAction)flipToTheOtherView:sender {
FlippedViewController *foo=[[FlippedViewController alloc] init];
foo.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:foo animated:YES];
[foo release];
}
Pro iPad s jeho velkou obrazovkou máme navíc možnost využít několik specifických výjimek z dříve zmíněného obecného pravidla, že hlavní rámec musí překrývat celou obrazovku a být neprůhledný. Na rozdíl od iPhone můžeme v aplikacích pro iPad vedle atributu modalTransitionStyle nastavit také podobný atribut modalPresentationStyle; možné hodnoty jsou tyto:
• UIModalPresentationFullScreen: standardní překrytí celé obrazovky, tak, jak je to běžné na iPhone;
• UIModalPresentationPageSheet: je-li zařízení orientováno na výšku ("portrait"), funguje stejně jako minulý případ. Pokud je ale iPad orientován na šířku ("landscape"), nový rámec je stále pouze tak široký, jaká je v této orientaci výška obrazovky; po stranách tedy zůstanou volné okraje skrz něž je viditelný starý rámec (překrytý šedým poloprůhledným závojem);
• UIModalPresentationFormSheet: jak výška, tak i šířka nového rámce jsou menší, než velikost obrazovky iPadu. Starý rámec – opět překrytý šedým poloprůhledným závojem – je vidět všude kolem. Nový rámec je vycentrován na obrazovce. Běžně se tato varianta používá v případech, kdy je třeba v novém rámci vkládat text; po otevření obrazovky se totiž nový rámec posune automaticky nahoru, takže je stále viditelný celý;
• UIModalPresentationCurrentContext: atribut se dědí od nadřízeného řídicího objektu.
Zpráva dismissModalViewControllerAnimated:
Chceme-li opět rámce modálního řídicího objektu z obrazovky odstranit a vrátit se k původnímu vzhledu a řídicímu objektu, použijeme zprávu dismissModalViewControllerAnimated:. Můžeme ji stejně dobře poslat kterémukoli z obou objektů – jak starému, tak i novému; ačkoli o návrat do původního stavu se vždy fakticky stará ten starý, nový mu tuto zprávu automaticky předá. (Stojí asi za zmínku, že projektové vzory v Xcode této služby nevyužívají a namísto toho obsahují zbytečně komplikované explicitní předávání zprávy "starému" řídicímu objektu. Není však žádný důvod to dodržovat a tak zbytečně komplikovat vlastní kód.)
Nejjednodušší kód v novém řídicím objektu pro odstranění jeho rámců by mohl vypadat nějak takto (v našem posledním příkladu by tedy tato metoda byla součástí třídy FlippedViewController):
-(IBAction)flipBackToTheOriginalView:sender {
[self dismissModalViewControllerAnimated:YES];
}
Vyžádáme-li si argumentem YES animaci, použije se odpovídající inverzní animace k té, jíž se rámce na obrazovku dostaly, a jež je stále uložena v atributu modalTransitionStyle.
Více řídicích objektů nad sebou
Výše popsaným způsobem přes sebe můžeme "navrstvit" libovolně mnoho řídicích objektů: kořenový řídicí objekt, jehož rámec je uložen do okna kódem z prvého příkladu na začátku článku, tak může presentovat rámce řídicího objektu A; ten sám přes sebe překryje rámce řídicího objektu B, který zase presentuje řídicí objekt C, a tak dále.
Aby si knihovní kód "udržel přehled", obsahují řídicí objekty dva šikovné atributy, jež můžeme využít samozřejmě také programově, kdykoli se nám to hodí:
@property(nonatomic,readonly)UIViewController*modalViewController
@property(nonatomic,readonly)UIViewController*parentViewController
Pokud je řídicí objekt sám překryt rámci nějakého jiného řídicího objektu – tj. poté, kdy sám dostal zprávu presentModalViewController:animated: –, je tento překrývající řídicí objekt uložen v atributu modalViewController.
Jestliže řídicí objekt sám nějaký jiný řídicí objekt překrývá – tj. poté, kdy sám byl argumentem zprávy presentModalViewController:animated: zaslané jinému řídicímu objektu –, je tento překrytý řídicí objekt uložen v atributu parentViewController.
Pokud se takto vzájemně překrývá celý řetěz řídicích objektů a my některému z nich pošleme zprávu dismissModalViewControllerAnimated:, platí následující logika:
• pokud příjemce zprávy nemá žádný modalViewController (obsahuje-li tento atribut hodnotu nil), nedělá nic jiného, než že ji předá objektu parentViewController (tuto službu jsme si vysvětlili v minulém odstavci);
• má-li naopak příjemce modalViewController, budou právě rámce tohoto řídicího objektu (tedy právě toho, který příjemce překrývá) a všech případných dalších, odstraněny.
Ve druhém případě navíc platí, že vyžádáme-li si animaci argumentem YES, proběhne pouze u rámců nejvyššího viditelného řídicího objektu; všechny případné další budou odstraněny najednou a bez animací.
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