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
XIBy chyby
17. srpna 2011, 00.00 | V dnešním pokračování seriálu o práci ve vývojovém prostředí Xcode se začneme zabývat editací "XIBů" – objektových sítí, sloužících především (ale zdaleka ne výhradně) pro pohodlné sestavení grafického uživatelského rozhraní aplikace.
Postupně jsme se už naučili základům práce s integrovaným vývojovým prostředím Xcode: umíme nastavovat jeho předvolby, prošli jsme si jeho hlavní ovládací prvky. Podrobně jsme si ukázali, jak pracovat s nastaveními projektu a cíle, a minule jsme se zběžně zastavili u editace zdrojového textu.
Ačkoli zde bychom se mohli zdržet velmi dlouho, využijeme toho, že pro každého, kdo delší dobu pracuje v prostředí Mac OS X, je editor zdrojového textu velmi intuitivní, a jen poměrně málo se liší od toho, který důvěrně známe z Xcode 3; snad jediné podstatnější rozdíly jsou v zobrazení definice a nápovědy k symbolu (nyní k tomu neslouží poklepání, ale jednoduché klepnutí; je ale zapotřebí při něm držet stisknutou klávesu Command nebo Alt).
Práci se zdrojovými texty tedy uzavřeme, a místo toho přejdeme k oblasti, již jsme v našem seriálu poměrně dlouho zanedbávali, a která navíc je v Xcode 4 poměrně zásadním způsobem změněna: k práci s objektovými sítěmi NIB/XIB. Dnes si především podrobně vysvětlíme, o co vlastně jde.
Co to vůbec je?
Pro čtenáře, kteří nesledují náš seriál od samotného začátku, je možná vhodné začít trochu podrobnějším vysvětlením co to vlastně takový NIB je: na první pohled se totiž trochu podobá "resource souboru" ze starého Mac OSu či některých vývojových prostředí z jiných systémů, v němž je prostě uveden seznam grafických objektů. NIB je ale něco daleko jednoduššího – a zároveň flexibilnějšího.
Krátká odbočka k rámcům
Aby byl následující kód srozumitelný, je třeba vědět, že to, co na obrazovce iPhone nebo iPadu vidíme, je z hlediska programu hierarchickou strukturou tzv. rámců (representovaných třídou UIView a jejími konkrétními podtřídami, mezi nimiž je mj. např. okno UIWindow, textové pole UILabel nebo tlačítko UIButton). Každý rámec může obsahovat libovolně mnoho rámců podřízených; ty jsou pak zobrazovány nad ním a jeho obsah překrývají. Poměrně detailně jsme se s touto stukrutou – až na předpony NS namísto UI a na to, že tam má nepatrně odlišné postavení – seznámili v jednom z předcházejících dílů našeho seriálu.
Programově sestavené GUI
Představme si nejprve na chvíli, že žádné NIBy nemáme k dispozici, a že musíme grafické uživatelské rozhraní aplikace sestavit programově – to je samozřejmě možné a nic nám v tom nebrání. Odpovídající kód by pro hodně, hodně jednoduchou aplikaci v iOSu mohl vypadat kupříkladu nějak takto:
UIWindow *window=[[UIWindow alloc]
initWithFrame:CGRectMake(0, 0, 320, 480)];
UILabel *label1=[[[UILabel alloc]
initWithFrame:CGRectMake(10, 40, 300, 30)] autorelease];
label1.font=[UIFont boldSystemFontOfSize:20];
label1.textAlignment=UITextAlignmentCenter;
label1.textColor=[UIColor blackColor];
label1.text=@"Hello";
[window addSubview:label1];
UILabel *label2=[[[UILabel alloc]
initWithFrame:CGRectMake(10, 100, 300, 30)] autorelease];
label2.font=[UIFont boldSystemFontOfSize:20];
label2.textAlignment=UITextAlignmentCenter;
label2.text=@"World";
[window addSubview:label2];
UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame=CGRectMake(10, 300, 300, 40);
[button setTitle:@"Tap here" forState:UIControlStateNormal];
[window addSubview:button];
Je to sice nepohodlné, ale naprosto korektní (pokud ponecháme stranou věci jako fixní velikost obrazovky, jež nyní a tady řešit nemá smysl). Vidíme, že v takto sestaveném GUI bude na obrazovce okno, v něm dvě textová pole se standardním textem "Hello World", a jedno tlačítko. Celé bychom to mohli zobrazit třeba ve standardní metodě application: didFinishLaunchingWithOptions:, nějak takto:
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
UIWindow *window=[[UIWindow alloc]
initWithFrame:CGRectMake(0, 0, 320, 480)];
... výše uvedený kód ...
[window addSubview:button];
[window makeKeyAndVisible];
return YES;
}
Je asi zřejmé, že za cenu ukrutného nepohodlí bychom takto mohli sestavit kompletní plnohodnotnou aplikaci. My si místo toho ale ukážeme malý trik.
GUI uložené do souboru
Dejme tomu, že bychom při práci se složitějším grafickým uživatelským rozhraním zjistili, že programové vytváření všech grafických prvků je příliš pomalé – v praxi to je sice krajně nepravděpodobné, ale třeba v případě nějakého velmi náročného výpočtu poloh jednotlivých rámců principiálně možné.
Takový problém by se dal řešit třeba tak, že bychom celou strukturu vytvořili pouze při prvém spuštění aplikace; pak bychom ji uložili do souboru, a při každém dalším spuštění bychom ji už jen hotovou jednorázově načtli.
Znáte služby, jež standardní knihovny nabízejí pro archivaci (téměř) libovolných objektů do souboru a jejich opětovné načtení? Jsou velmi jednoduché; podrobně jsme si o nich povídali už před delším časem, ale nyní nám stačí jen ta nejzákladnější znalost – na jejím základě bychom mohli kód upravit zhruba nějak takto:
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
NSURL *p=[[[NSFileManager defaultManager]
URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask appropriateForURL:nil
create:NO error:NULL]
URLByAppendingPathComponent:@"GUI.pmnib"];
UIWindow *window=[[NSKeyedUnarchiver
unarchiveObjectWithFile:p.path] retain];
if (!window) {
initWithFrame:CGRectMake(0, 0, 320, 480)];
... výše uvedený kód ...
[window addSubview:button];
[NSKeyedArchiver archiveRootObject:window toFile:p.path];
}
[window makeKeyAndVisible];
return YES;
}
Je asi zřejmé, že – a proč – takováto aplikace bude dělat přesně to, co po ní chceme, a hlavně, že celé GUI programově sestavíme pouze jednou; při každém dalším spuštění se již načte hotové ze souboru. Můžeme dokonce klidně zjednodušit hlavní metodu delegáta aplikace na
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
NSURL *p=... beze změny ...
UIWindow *window=[[NSKeyedUnarchiver
unarchiveObjectWithFile:p.path] retain];
[window makeKeyAndVisible];
return YES;
}
a dokud nepřijdeme o obsah složky "Documents", vše bude perfektně fungovat.
S tím by se dala dělat spousta věcí...
Po nějaké době bychom si nejspíše uvědomili, že tento přístup nabízí řadu velmi zajímavých a šikovných možností:• takto uložené GUI můžeme využít i v jiné aplikaci, nejen v té, v níž jsme je vytvořili: stačí je do ní překopírovat a tam týmž způsobem načíst;
• nemusíme mít celé GUI v jediném souboru; můžeme jeho různé části uložit do různých souborů a ty načítat podle potřeby;
• časem bychom asi zjistili, že se nám vyplatí napsat si specialisovaný editor těchto našich "pmnibů" – aplikaci, jež takovéto GUI službou unarchiveObjectWithFile: načte, pak umožní měnit jeho obsah (tedy texty v UILabelech, písma, umístění rámců....), a výsledek opět uloží službou archiveRootObject:toFile:...
... a v tu chvíli už je náš formát pmnib skutečně poor man's NIB; od skutečných NIBů se koncepčně vůbec neliší (jen by k němu bylo třeba doplnit pár specialisovaných služeb pro větší pohodlí).
Je poměrně důležité rozumět tomu, co to NIB je – a nyní je nám to již zcela jasné: je právě takovou objektovou sítí, uloženou do souboru (a zpracovanou speciálním editorem), jak jsme si to právě ukázali. Jen s trochou specialisovaných služeb pro větší pohodlí navíc, ale ty z hlediska koncepce nejsou důležité a na principu zhola nic nemění.
NIBy a XIBy
Ve vývojovém prostředí NeXT tomu bylo od samého počátku před čtvrt stoletím právě popsaným způsobem – archivované objekty se ukládaly do objektových sítí NIB, a specialisovaný editor pro práci s nimi byl Interface Builder. Stejně tak dlouhá léta poté, kdy toto vývojové prostředí koupila firma Apple.
Poměrně nedávno ale některé nevýhody binárního formátu začaly opravdu vadit: nemožnost snadno prohledávat takové soubory a přejmenovávat údaje v nich vadila refactoringu; systémy správy zdrojových textů v nich nemohly hledat rozdíly a spojovat je, a tak dále.
Firma Apple proto v podstatě převedla archiv NIBů do textové podoby; tuto textovou podobu nazvala XIB. Editor Interface Builder nadále zpracovává tuto textovou podobu – a do binárního NIBu se celá objektová síť převede až při sestavování aplikace. Na principu celé věci to ale nic nemění; jde jen o drobnou komplikaci, jež přináší za cenu "zbytečného" překladu o něco bohatší možnosti při práci s projektem.
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