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 - 26. Jak se dělá UIViewController
26. ledna 2011, 00.00 | Jaké je postavení řídicích objektů rámců, k čemu slouží a proč se bez nich jen těžko můžeme obejít už víme. Dnes se pustíme do jejich konkrétního programátorského rozhraní. A začneme samozřejmě tím základním – jejich výrobou.
Nejzákladnějším – ačkoli, jak víme, zdaleka ne jediným – způsobem, jak vytvořit objekt nějaké třídy, je poslat této třídě standardní zprávu alloc a nově vytvořenou instanci inicializovat pomocí vhodné zprávy init... – to jsme si ukazovali už hodně dávno, a od té doby se nic nezměnilo.
To je s třídou UIViewController jednoduchá: nabízí totiž pouze jediný inicializátor (vedle těch zděděných z nadtříd nebo připojených z protokolů; k tomu se ještě za chvilku vrátíme, ale zde to není příliš podstatné):
-initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundle;
Tato metoda korektně inicializuje instanci řídicího objektu rámce a je také jejím designovaným inicializátorem (takže pokud vytváříme ve vlastních podtřídách UIViewController nové metody initWith..., měli bychom v nich použít právě "[super initWithNibName:... bundle:...]", případně bychom, je-li to zapotřebí, měli právě tuto metodu reimplementovat – podrobně jsme si mechanismus designovaných inicializátorů vysvětlili zde).
Oba dva argumenty souvisí s možností načíst kompletní strukturu rámců, spravovanou právě vytvořeným a inicializovaným řídicím objektem, z objektové sítě uložené v souboru NIB: prvý určuje jméno tohoto souboru (příponu ".nib" není třeba uvádět), druhý složku, v níž se má tento soubor hledat – nikoli přímo pomocí její cesty, nýbrž prostřednictvím třídy NSBundle; v daleko nejběžnějším případě, kdy je NIB přímo součástí samotné aplikace, můžeme namísto "[NSBundle mainBundle]" použít hodnotu nil.
Řídicí objekt si obsah tohoto NIBu načte automaticky ve chvíli, kdy to bude zapotřebí: obecně (opět nikoli bez výjimek, ale v naprosté většině případů) platí to, že všechny rámce, spravované jedním řídicím objektem, jsou uloženy v samostatném NIBu, v němž nebývá už nic jiného; tím se ale budeme podrobněji zabývat až příště.
Hodnotu nil můžeme použít i pro argument nibName; má to smysl ve dvou vzájemně různých případech:
• jmenuje-li se soubor NIB stejně jako třída (tj. pracujeme-li např. s třídou "@interface MyVC:UIViewController" a jsou-li odpovídající rámce uloženy v souboru "MyVC.nib") – řídicí objekt se po NIBu tohoto jména dívá automaticky;
• nechceme-li načítat NIB vůbec, typicky proto, že rámce pro grafické uživatelské rozhraní sestavíme také programově (jak to udělat si ukážeme také příště). Pokud totiž byla hodnota argumentu nibName nulová a pokud se soubor NIB se jménem odpovídajícím třídě nepodaří nalézt, řídicí objekt automaticky vytvoří hlavní rámec jako instanci třídy UIView.
Nakonec se ještě můžeme zběžně zmínit o tom, že programátoři Apple (na rozdíl od mnoha programátorů třetích firem) vlastní API dobře znají a korektně zacházejí s designovanými inicializátory; proto můžeme zcela bezpečně používat také inicializátor init, zděděný od třídy NSObject – je zcela ekvivalentní použití zprávy initWithNibName:bundle: s oběma argumenty nil (není-li snad někomu zřejmé, proč tomu tak je, vizte prosím opět popis mechanismu designovaných inicializátorů).
Načtení řídicího objektu z NIBu
Poměrně často namísto programového vytvoření řídicího objektu využíváme schopnost objektových sítí NIB obsahovat objekty libovolných tříd (nejen tedy rámce grafického uživatelského rozhraní), a řídicí objekt vytváříme v odpovídajícím zdrojovém souboru XIB; jeho instance se tedy vytvoří načtením odpovídajícího NIBu (který, jak víme, vznikne překladem XIBu při sestavování aplikace) do paměti. Právě tak tomu je i v řadě projektových vzorů Xcode a právě tak tomu bylo i v našem bouřlivém příkladu, jehož vnitřní strukturu jsme si podrobně popsali zde.
Chceme-li do nějakého NIBu řídicí objekt rámce sami uložit, je to velmi jednoduché:
• v panelu "Library" najdeme "View Controller" – můžeme pro lepší přehled panel pomocí rozevírací nabídky v jeho horní části přepnout do režimu "Controllers" – a vhodíme jej myší do hlavního okna XIBu;
• zde tento objekt označíme, panel inspektoru přepneme do režimu "Identity", a v poli "Class" zapíšeme (nebo vybereme z rozevírací nabídky) jméno třídy, jejíž má být tento řídicí objekt instancí (např. tedy "MyVC" v minulém příkladu "@interface MyVC:UIViewController", pokud bychom řídicí objekt vkládali do NIBu).
Ačkoli je samozřejmě v principu možné, aby rámce, jež řídicí objekt spravuje, byly uloženy v témže NIBu, v němž je sám tento řídicí objekt, v praxi se to z řady dobrých důvodů nedělává. Je-li tedy sám řídicí objekt uložen v nějakém NIBu, jsou jeho rámce typicky v NIBu jiném (jehož obsah si řídicí objekt načte automaticky ve chvíli, kdy to bude zapotřebí, přesně stejně, jako kdybychom jej vytvořili programově podle minulého odstavce).
Pokud se tento NIB jmenuje stejně jako třída, jíž je řídicí objekt instancí, o nic se starat nemusíme – takový NIB se načte automaticky, stejně, jako když jsme při programovém sestavování použili nil v argumentu nibName. Co ale v případě, kdy máme rámce uloženy v NIBu jiného jména?
V tomto případě je třeba přepnout panel inspektoru do režimu "Attributes"; zde nalezneme jako předposlední položku textové pole "NIB name", a do něj zapíšeme požadované jméno. Toto textové pole je tedy při načítání řídicího objektu z NIBu ekvivalentem argumentu nibName při vytváření programovém.
Pro úplnost poznamenejme, že pro sestavování struktury založené na řídicích objektech pro "navigační" nebo "tabbarovou" aplikaci máme k dispozici v Interface Builderu poněkud rozšířené možnosti; to si ale ukážeme až později, až se budeme těmito strukturami speciálně zabývat.
Jedno, nebo druhé!
Pozor na to, abychom nevytvořili dvě instance téhož řídicího objektu, jež se budou prát o stejné postavení – jednu programově, druhou načtením z NIBu. Zkušeným programátorům v prostředí Cocoa se to stát nemůže; začátečníci, kteří nejsou dosud dostatečně zběhlí v práci s NIBy, však tuto chybu dělají poměrně často – zvláště pak tam, kde je řídicí objekt do NIBu, typicky "MainWindow", uložen automaticky na základě projektového vzoru Xcode. Začátečník pak pomocí nějakého copy/paste zároveň pro týž řídicí objekt udělá alloc/initWithNibName:bundle: namísto toho, aby použil jen obsah vhodného "outletu", a neštěstí je hotové.
Pak se stane to, že některé vazby vedou na jeden z řídicích objektů, jiné na druhý; každý objekt také má samozřejmě vlastní rámce (protože oba dva řídicí objekty – jak ten z MainWindow.nib, tak i ten vytvořený pomocí alloc/initWithNibName:bundle: – si načetly vlastní NIB), z nichž ale jen jedna sada je viditelná. Aplikace pak funguje "naprosto divně", stává se, že "do objektu uložíme hodnotu a ona tam není" apod.
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