Programování pro iOS - 33. Více o UINavigationControlleru - 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

 

Kde se narodil známý fotograf František Drtikol?

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

Seriály

Více seriálů



Informace

Programování pro iOS - 33. Více o UINavigationControlleru

23. března 2011, 00.00 | Minule jsme si ukázali základy práce se standardním řídicím objektem pro hierarchické zobrazení – tedy s třídou UINavigationController. Dnes se seznámíme s některými jejími dalšími možnostmi.

V předchozím dílu našeho seriálu jsme se naučili vyrobit programově řídicí objekt UINavigationController pomocí standardního inicializátoru initWithRootViewController:, a ukázali jsme si také na konkrétním příkladu princip jeho použití – včetně standardní služby pushViewController:animated: pro zobrazení další úrovně v hierarchii. Dnes si ukážeme některé jeho další často využívané služby a možnosti.

Titulek

Pokud si sestavíme a spustíme kód z minulého dílu, uvidíme, že sice vše funguje jak má – tedy že klepnutím na odkazy "Nested N items" se skutečně posuneme níže v hierarchii, že se automaticky vlevo nahoře objeví standardní tlačítko "Back", a že jeho pomocí se můžeme zase vrátit – ale obrazovka vypadá "divně". To proto, že v záhlaví obrazovky není žádný titulek aktuální stránky. Pojďme to napravit!

Vůbec nejjednodušší je titulek přímo přiřadit řídicímu objektu aktuálního rámce – v praxi to takhle také budeme dělat asi nejčastěji. Řídicí objekt navigátoru je pak dostatečně "chytrý" na to, aby při zobrazení libovolného řídicího objektu do záhlaví automaticky vložil jeho nadpis.

A jak to udělat? Jednoduše: v kódu řídicího objektu rámce prostě implementujeme metodu title, a vrátíme z ní požadovaný text – v našem případě by to mohlo vypadat třeba takto:

@implementation SelectionVC
...
-(NSString*)title {
  return [NSString
          stringWithFormat:@"Choose from %u items",
          self.items.count];
}
...
@end

To je celé a nic jiného není zapotřebí – můžeme to zkusit a hned uvidíme, že se titulek zobrazuje správně.

Jenže je tu drobný problém, který ve většině případů problémem není – ale u nás zrovna ano: UINavigationController totiž nejenže zobrazuje titulek aktuálního řídicího objektu v záhlaví – což chceme –, ale také zobrazuje titulek řídicího objektu, který mu v hierarchii předchází, v tlačítku pro návrat zpět!

V běžných situacích je to přesně to, co chceme – pokud např. v hierarchii aplikace Mail sestoupíme do konkrétní zprávy, je jistě správně mít v tlačítku pro návrat zpět "Inbox" a nikoli "Back".Jenže zrovna v našem případě tomu tak výjimečně není, a chtěli bychom tlačítko "Back" zachovat. Abychom to dokázali, musíme využít přístupu přímo k záhlaví obrazovky.

Přístup k záhlaví

Záhlaví obrazovky, jež se zobrazuje, kdykoli je aktuální řídicí objekt vložen v nějakém UINavigationControlleru, je kupodivu přístupné prostřednictvím veřejného API: jedná se o instanci třídy UINavigationItem, a odkaz na ni vždy najdeme v atributu

@property(nonatomic, readonly, retain)
               UINavigationItem *navigationItem;

Záhlaví nám umožňuje přímý přístup k titulku (a také k některým dalším prvkům GUI, k nimž se vrátíme za chvilku), prostřednictvím atributu title. Můžeme tedy titulek nastavovat přímo programově (namísto toho, abychom jen implementovali metodu title a nechali UINavigationController, aby se o to staral sám).

V našem případě tedy potřebujeme

a) nastavit titulek ve chvíli, kdy se řídicí objekt rámce dostává na obrazovku, aby jeho vlastní záhlaví titulek obsahovalo;

b) zrušit jej ve chvíli, kdy je řídicí objekt rámce odstraněn z obrazovky – aby záhlaví podřízeného rámce obsahovalo standardní tlačítko "Back".

Jednou z možností, jak toho docílit, je využít standardní zprávy, jež řídicí objekt rámce dostává při změnách zobrazení, a které již známe dávno – můžeme tedy implementovat např. tuto dvojici metod:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationItem.title=[NSString
            stringWithFormat:@"Choose from %u items",
                self.items.count];
}
-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.navigationItem.title=nil;
}

a vše bude fungovat jak má.

Poznámka: mohlo by se zdát, že by mělo stačit týmž způsobem měnit přímo obsah vlastního atributu title (např. udělat si pro něj instanční proměnnou, a její obsah nastavovat v metodách viewWillAppear: a viewWillDisappear:). Ukazuje se ale, že to nefunguje – UINavigationController si totiž obsah "navigačních itemů" cacheuje, takže takovéto změny se neuplatní.

Ačkoli v praxi nejspíše jen výjimečně potřebovat přímo takovou změnu titulku, jakou jsme si právě teď ukázali, přístup k titulku prostřednictvím atributu navigationItem se hodí, kdykoli chceme jeho hodnotu dynamicky měnit z libovolných důvodů – mohli bychom v něm např. zobrazovat informace, týkající se posledního klepnutí apod.

Příkazová tlačítka

Záhlaví z atributu navigationItem ovšem můžeme využít – a v typické aplikaci také využíváme – jinak, než jen pro přímou změnu titulku. Daleko zajímavější jsou jeho atributy

@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;
@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;

Jejich prostřednictvím můžeme určovat, jaký prvek uživatelského rozhraní se objeví na levém a pravém okraji záhlaví. Samozřejmě, že nastavíme-li pomocí atributu leftBarButtonItem ten vlevo, nezobrazí se standardní tlačítko "Back" vůbec; zde tedy musíme být opatrní; doprava ale můžeme pomocí atributu rightBarButtonItem uložit v zásadě cokoli.

Naprosto typickým prvkem tabulek je např. tlačítko "Edit", umožňující změny jejich obsahu. Jeho zobrazení zajistíme pomocí jednoduchého příkazu

self.navigationItem.rightBarButtonItem=self.editButtonItem;

který můžeme umístit – vzhledem k již zmíněnému cacheování "navigačních itemů" – třeba už do metody init...; díky tomu, že náš řídicí objekt dědí od třídy UITableViewController, bude automaticky a bez nutnosti psát další kód fungovat téměř vše vyjma vlastního smazání řádku – k tomu bychom již potřebovali přidat další metodu delegáta, ale to si ukážeme až příště.

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: