Programování pro iOS - 32. Řídicí objekt pro tabulky - 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

Programování pro iOS - 32. Řídicí objekt pro tabulky

9. března 2011, 06.00 | V současnosti se náš seriál soustředí na řídicí objekty rámců. V minulých dílech jsme se seznámili s obecnými službami, jež nám nabízí sama třída UIViewController (a tedy také všechny její podtřídy); dnes se začneme věnovat některým speciálním řídicím objektům, jež iOS nabízí.

Docela určitě nejjednodušším ze všech specializovaných řídicích objektů rámců je UITableViewController – řídicí objekt, specializovaný na ovládání tabulky. Proto jím dnes začneme, a na složitější řídicí objekty – jako je třeba UITabViewController – se podíváme v příštích dílech.

Co vlastně umí?

Služeb, které nabízí UITableViewController navíc oproti své nadřízené třídě UIViewController, není mnoho, a už řadu programátorů určitě napadlo, že je otázka, stálo-li firmě Apple vůbec za to jej vytvářet v API jako samostatnou třídu. Jedná se pouze o následující funkce:

• pokud necháme řídicí objekt, aby sám vytvořil standardní rámec (tedy nepoužijeme-li ani XIB, ani některou z možností pro jeho programové sestavení), bude to rámec třídy UITableView, nikoli UIView;

• pro pohodlný přístup bez přetypování také třída nabízí atribut tableView; ten vždy obsahuje kořenový rámec (stejně jako zděděný atribut view), ale navíc má správný typ. Neobjektová ošklivost, ale vzhledem k nešťastně navrženým atributům šikovná...

• nevyžádáme-li si jinak, řídicí objekt automaticky sám sebe uloží do atributů dataSource a delegate svého rámce – aniž bychom se o to tedy museli explicitně starat, bude mu dodávat data a bude řídit jejich vzhled;

• řídicí objekt po inicializaci pošle rámci zprávu reloadData;

• řídicí objekt před zobrazením tabulky může – chceme-li – zrušit seznam vybraných řádků (v závislosti na nastavení atributu clearsSelectionOnViewWillAppear);

• po zobrazení tabulky na chvilku zobrazí scollery, aby uživatel měl představu o tom, jaká část tabulky je zobrazena;

• podporuje přepínání tabulky do editačního režimu pomocí odpovídajícího tlačítka (standardně – ale ne nutně – "Edit" v pravém horním rohu).

Vidíme, že jde o poměrně jednoduchou skupinu služeb, jež by bylo poměrně pohodlné implementovat "ručně"; přesto ale to, že je máme k dispozici hotové, dokáže nějaký ten čas ušetřit.

Co neumí?

Asi hlavní nevýhodou třídy UITableViewController je to, že její atribut tableView povinně musí odkazovat na týž objekt jako zděděný atribut view – a tento objekt musí být řízená tabulka. Není tedy speciálně možné s využitím služeb této třídy implementovat správu obrazovky, v níž tabulka (rámec UITableView) není jediným a kořenovým objektem, ale pouze jedním z více prvků složitějšího GUI.

Potřebujeme-li sestavit takovou strukturu rámců, nezbývá, než použít "obyčejný" UIViewController, a všechny výše zmíněné služby (resp. ty z nich, jež skutečně potřebujeme, ale obvykle to bývá většina z výše zmíněných) si implementovat sami.

V ostatních případech bývá pohodlnější vytvořit řídicí objekt jako dědice UITableViewController a implementovat jen to, co je "navíc".

Služby

Programátorské rozhraní, které třída UITableViewController nabízí, je velice jednoduché, a téměř celé jsme si je již popsali: oproti třídě UIViewController zde jsou totiž pouze tři novinky, a dvě z nich již známe – atribut

@property(nonatomic, retain) UITableView *tableView;

pro "správně otypovaný" přístup ke kořenovému rámci, stejně jako atribut

@property(nonatomic) BOOL clearsSelectionOnViewWillAppear;

jehož hodnota (standardně YES) rozhoduje, zda řídicí objekt vždy před zobrazením tabulky zruší seznam vybraných řádků, jsme si popsali výše.

Třetí změnou je nový inicializátor

-(id)initWithStyle:(UITableViewStyle)style;

Tabulky v iOS jsou velmi flexibilní a podporují hodně bohatou paletu různých vzhledů, od zcela klasické tabulky až po to, co používá většina aplikací pro nastavování parametrů – spustíte-li aplikaci "Settings", uvidíte tabulku. Těm klasickým odpovídá tzv. obyčejný styl UITableViewStylePlain (a to je také standardní hodnota, pokud použijeme některý ze zděděných inicializátorů); tomu, co známe např. z aplikace "Settings", odpovídá styl "skupinový" – UITableViewStyleGrouped.

Pokud necháme UITableViewController tabulku automaticky vytvářet – a jak si ukážeme níže, je to poměrně běžné –, můžeme si právě tímto argumentem vyžádat její vzhled. Pokud samozřejmě tabulku načteme z XIBu nebo vytvoříme programově, bude mít ten vzhled, jaký je v XIBu nebo jaký si vyžádáme při jejím vytváření.

Jednoduchá ukázka

Samozřejmě, že do řídicího objektu tabulky můžeme přidat řadu služeb; bezpodmínečně ale musíme doplnit přinejmenším metody pro řízení tabulky – služby jejího datového zdroje a delegáta. Ponecháme-li tedy stranou nepravděpodobnou (ale ovšem možnou) situaci, v níž by tabulka měla odlišný datový zdroj, nikdy nepoužijeme přímo třídu UITableViewController, ale vždy nějakou její vlastní podtřídu.

Naproti tomu je velmi častý případ to, že pro tabulku nepoužijeme žádný XIB, a vše, co je zapotřebí, nastavíme čistě programově.

Jako ukázku si implementujeme velmi jednoduchou třídu, která nám umožní zobrazovat tabulky předem daných textů a vybírat z nich:

@interface SelectionVC:UITableViewController
+(SelectionVC*)selectionWithList:(NSArray*)items;
@end
extern NSString * const SelectionVCNotification;

Naše API je naprosto triviální: nabízí jen jedinou službu, selectionWithList:; zde pole "items" obsahuje texty, z nichž můžeme vybírat. Jakmile hotový řídicí objekt rámce umístíme na obrazovku – nejspíše asi pomocí služby presentModalController:animated: – řídicí objekt zobrazí tyto texty v tabulce a nechá uživatele zvolit některý z nich. Zvolený index pak bude rozeslán pomocí notifikace SelectionVCNotification.

Ani implementace, jak uvidíme, nebude příliš složitá – začneme definicí potřebných atributů, a protože není třeba, aby byly veřejné, použijeme k tomu tzv. rozšíření, jež bude spolu s vlastní implementací v témže zdrojovém souboru:

@interface SelectionVC
@property (retain,nonatomic) NSArray *items;
@end
@implementation SelectionVC
@synthesize items, selectedIndex;
...

V dalším kroku pak implementujeme standardní inicializační metodu, odpovídající nutnou metodu dealloc, a také jedinou veřejnou službu selectionWithList:...
-initWithItems:(NSArray*)ia {
  if (!(self=[super init])) return nil;
  self.items=ia;
  return self;
}
-(void)dealloc {
  self.items=nil;
  [super dealloc];
}
+(SelectionVC*)selectionWithList:(NSArray*)items {
  return [[[self alloc] initWithItems:items] autorelease];
}
...

Zbývá už jen implementovat služby datového zdroje a delegáta tabulky. My jsme se s nimi již setkali na začátku v ukázce "bouřlivé" aplikace, takže pro nás nebudou žádnou zásadní novinkou – z celé bohaté palety možných metod stačí implementovat tři, dvě pro zobrazení obsahu tabulky a třetí pro výběr jejího řádku:

...
-(NSInteger)tableView:(UITableView*)tv
  numberOfRowsInSection:(NSInteger)section {
  return self.items.count;
}
-(UITableViewCell*)tableView:(UITableView*)tv
  cellForRowAtIndexPath:(NSIndexPath*)ip {
  UITableViewCell *cell=nil;
  if (!(cell=[tv dequeueReusableCellWithIdentifier:@"0"]))
    cell=[[[UITableViewCell alloc]
      initWithStyle:UITableViewCellStyleDefault
      reuseIdentifier:@"0"]
      autorelease];
  cell.textLabel.text=[self.items objectAtIndex:ip.row];
  return cell;
}
-(NSIndexPath*)tableView:(UITableView*)tv
  willSelectRowAtIndexPath:(NSIndexPath*)ip {
  [[NSNotificationCenter defaultCenter]
    postNotification:SelectionVCNotification object:self
    userInfo:[NSDictionary
      dictionaryWithObject:[NSNumber numberWithInteger:ip.row]
      forKey:@"row"]];
    return nil;
}
@end

A to je celé.

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: