XIBy chyby - MujMAC.cz - Apple, Mac OS X, Apple iPod

Odběr fotomagazínu

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:

Soutěž

Sponzorem soutěže je:

IDIF

 

Odkud pochází fotografka Anne Erhard?

V dnešní soutěži hrajeme o:

Seriály

Více seriálů



Informace

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):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Tipy a Triky  

 » Rubriky  » Začínáme s  

 » Rubriky  » Software  

 

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: