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

 

Odkud pochází fotografka Anne Erhard?

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

Seriály

Více seriálů



Software

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  

Diskuse k článku

 

Vložit nový příspěvek   Sbalit příspěvky

 

lepsie back button

Autor: iMartin Muž

Založeno: 27.03.2011, 19:57
Odpovědí: 0

podla mna je elegantnejsie nastavenie tlacidla spet takto:

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@\"Back\" style:UIBarButtonItemStyl
eBordered target:nil action:nil];
self.naviga
tionItem.backBarButtonIte
m = backButton;
[backButton release];

a viete si zvolit akykolvek text, nie iba \"Back\"

Odpovědět na příspěvek

RE: lepsie back button

Autor: OC Muž

Založeno: 28.03.2011, 07:23

No, ano :) Tohle je služba, jíž jsem to nechtěl komplikovat --konkrétně tady by se hodila dobře, ale za běžných okolností se použije poměrně málokdy, aspoň tedy podle mých osobních zkušeností.

Každop
dně (to spíše pro ostatní, Vám to je určitě jasné) je u "backBarButtonItem" potřeba si dát pozor na to, že se nastavuje "o úroveň výše", tedy nikoli v tom VC, který je aktivní (a jeho titulek je v záhlaví), ale v tom, na nějž se přejde zpátky tím tlačítkem. Ono je to celkem logické -- čí titulek by tam byl normálně, toho "backBarButtonItem" tam je místo toho.

Jinak zrovna to, že lze zadat libovolný text, je kapku dvojsečné -- my obvykle nechceme "nějaký text", ale standardní systémový "Back" (který se automaticky lokalizuje do všech jazyků, jež iOS podporuje, atd.)

Odpovědět na příspěvek

RE: RE: lepsie back button

Autor: iMartin Muž

Založeno: 29.03.2011, 19:27

Zmena backButtonu pride vhod vtedy, ked tam chcete dat iba nejaku skratenu verziu nadpisu, aby sa neskracoval automaticky (klasickymi tromi bodkami). Napriklad z nadpisu "View Controller 32" spravite radsej "View 32" (a nie "View Con..." alebo klasicke "Back") aby ste ho rozlisili od "View Controller 33" napriklad.

Ja urcite preferujem sposob nastavenim "backBarButtonItem" za kazdych okolnosti. Tym sposobom, co ste popisali vznika jeden vizualny "problem". Ten nadpis sa meni az po skonceni animacie a na okamih vidno "stary" nadpis v backbutton. Nie je to katastrofa, no nie je to ani pekne.

No a este k tej lokalizaci: ten, kto lokalizuje aplikaciu nema problem nahodit o jeden string viac ;-)

Odpovědět na příspěvek

RE: RE: RE: lepsie back button

Autor: iMartin Muž

Založeno: 29.03.2011, 19:31

Pardon, ten nadpis by ste menil tesne pred animaciou a teda by na okamih zmizol. No vysledok je rovnaky.

Odpovědět na příspěvek

 

 

Vložit nový příspěvek

Jméno:

Pohlaví:

,

E-mail:

Předmět:

Příspěvek:

 

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

 

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

Uživatelské jméno:

Heslo: