Programování uživatelského rozhraní na iOS v Ackee (Storyboards vs. Xib vs. kód)
Tvorba uživatelského rozhraní na iOS je mezi vývojáři vždy vášnivým tématem. Dělí se totiž do dvou skupin: Jednak jsou tu ti, kteří milují vytváření GUI v Interface Builderu a pak také ti, kteří to nenávidí. Za 5 let co dělám na této platformě jsem vystřídal členství v těchto klubech hned několikrát, abych zjistil, že nic není černobílé a vše má svoje pro a proti. Abyste si tím nemuseli projít také, napsal jsem tento článek, který je takovým zevrubným shrnutím mých postřehů k těmto technologiím.
Storyboards vs. Xib vs. vlastní kód
Obecně máme tři možnosti, jak v iOS vytvořit uživatelské rozhraní. Nebudu je tady podrobně popisovat neboť k tomu existuje na internetu mnoho lepších článků. Spíše se chci zaměřit na problémy těchto přístupů a také na to, kdy je vhodné který z nich použít.
Storyboards
Storyboards jsou nejmladší ze zmíněných tří metod pro tvorbu uživatelského rozhraní. Jedná se o plátno, na kterém vytváříme design jednotlivých obrazovek, spojujeme je přechody a plníme statickými daty. Spousta programátorů je však neumí správně používat. Zásadní chybou (a také jsem se jí dříve dopouštěl) je uložit do jednoho storyboardu celou aplikaci. Storyboard je poté velice nepřehledný a hlavně brutálně pomalý. Aplikace by měla být rozdělena dle logických celků a každý z nich by měl mít vlastní storyboard. Jako příklad takového logického celku si můžete představit například tutoriál nebo checkout nákupního košíku.
Velkou výhodou storyboardů je jejich vizuální explicitnost. Každý, kdo se do něj podívá, vidí, jaký mají mezi sebou obrazovky vztah a jaké je flow aplikace. Další výhodou je rychlé prototypování, je totiž jednoduché si v Interface Builderu naklikat obrazovky i přechody mezi nimi. Pokud však chceme mezi obrazovkami přenášet i nějaká data, skončíme v případě Segues s obří „oifovanou“ metodu prepareForSegue.
Mezi nevýhody bych zařadil velice omezenou znovupoužitelnost kódu, především grafických elementů od velice podobných controllerů až po buňky v tabulce. Storyboardům se však nedá upřít jednoduchost, s kterou lze vytvořit například statickou tabulku na přihlášení uživatele, což je zrovna věc, která se v kódu dělá zbytečně složitě.
Xib
Xib je (stejně jako Storyboards) vytvořený v Interface Builderu, ale na rozdíl od Storyboardu reprezentuje pouze jeden konkrétní view element (view, controller, buňku tabulky, atd.) Tím sice ztrácí onu storyboardí přehlednost a nadhled, ale získává znovupoužitelnost a kontrolu nad logikou aplikace. Bohužel s sebou však nese i ostatní neduhy práce v Interface Builderu, o kterých si povíme níže.
Vlastní kód
O programování GUI v kódu by spousta lidí řekla, že je zdlouhavé a nudné. A v něčem mají určitě pravdu. Znám spoustu zábavnějších programátorských aktivit, než je psaní a pozicování Labelů. Přesto všechno si myslím, že je psaní GUI vlastním kódem mnohem lepší, než využití Interface Builderu. V několika bodech vysvětlím proč:
1. Znovupoužitelnost
Pokud aplikace není úplný cirkus, používá většinou jednotnou množinu prvků, které vypadají stejně napříč celou aplikací. V kódu si mohu tyto tlačítka, texty, avatary atd. připravit a všechny UI prvky mám pak na jednom místě. Navíc je mohu znovupoužít i napříč projekty.
Co se týká embedded controllerů, tak zde Storyboards jasně vedou. Jednoduchost s jakou mohu vložit jeden controller do druhého pomocí Interface Builderu je nedostižná, zato v kódu se jedná o zbytečně zdlouhavý a bolestivý proces.
2. Upravitelnost
Pokud potřebuji v aplikaci změnit nějakou barvu, velikost písma, styl písma apod., tak pokud mám správně navržený kód a dodržuji nějaké zásady, jednoduše požadovanou vlastnost upravím na jednom místě a změna se pak projeví úplně všude. Nezáleží pak už na tom, jestli dělám multibrandingovou aplikaci nebo vyvíjím agilně a mění se požadavky – vždy jsem schopný na změny reagovat velice pružně.
3. (Ne)roztříštěnost
V kódu mám vše na jednom místě. Zastánci IB (Interface Builder) budou oponovat, že si mohou design naklikat v IB a poté atributy jako font a barva nastavit globálně přes kód stejně jako já. Ano mohou a vím o tom, ale z mojí zkušenosti to přináší spíš víc problémů než užitku – část GUI logiky mají ve Storyboardu a část v kódu. Když se někdo ke kódu vrací, musí složitě hledat, kde se který atribut nastavuje. Nehledě na to, že některé atributy se přes IB nastavit ani nedají (ano mohu nastavit hodnoty do userInfo v IB, ale to je snad nejhorší programátorský pattern, který lze skrz XCode provézt). Zkrátka při psaní kódu je vše na jednom místě a každý ví, kde co hledat, i když je na projektu úplně nový.
4. Práce ve více lidech
Zde budu velice stručný. Zkoušeli jste někdy mergovat Storyboard/Xib? Příjemnou zábavu přeji :-)
5. Lokalizace
Přestože je lokalizace IB souborů možná, je dosti krkolomná a to i pro programátora, který se musí řídit storyboardem vygenerovanými identifikátory pro jednotlivé elementy. Nedej bože pak pro překladatele, který místo aby dostal klíč v podobě:
“login_field_name_title” = “Jméno”;
dostane
“l3f-5abg-iddqd” = “Jméno”;
Přestože tento problém lze řešit různými skripty a berličkami, je to zbytečná práce navíc.
6. Dynamika (o animacích ani nemluvě)
Storyboardy jsou prostě statické a žijeme v době, kdy jsou aplikace plné nejrůznějších animací a přechodů. Ty je v IB celkem problematické vyklikat, nemluvě o „vlastní hierarchii a vlastních kontejnerech“.
Poslední argument je hodně svázaný s následujícím bodem. Dost často totiž potřebujeme některé prvky v hierarchii skrýt v závislosti na datech, což opět zanáší roztříštěnost. Případně co když potřebuji v závislosti na těchto změnách měnit constraints jednotlivých views?
7. Autolayout (size classes)
Přestože se situace obecně v mnohém zlepšila, je pro mě (a pro mé kolegy) práce s constraintami v IB stále peklo. Musím označit konkrétní view a poté přes 2 klikátka nastavovat autolayout, nedej bože relationships a o nastavení nějakého globálního paddingu napříč aplikací ani nemluvím. Oproti tomu je práce s knihovnou typu Snapkit doslova potěšení. Všechny views layoutuji v jedné metodě logicky, jak jdou za sebou a díky velice čitelnému zápisu ihned vidím všechny constrainty i vazby a nemusím vůbec rozklikávat jednotlivé elementy.
Závěrem
Pokud jste dočetli až sem, je vám už asi jasné, jaký názor máme na tvorbu UI v Ackee. U nás se UI píše v kódu, pokud neexistuje závažný důvod (např. historický), proč to dělat jinak. Přestože jsem si vědom, že psaní a pozicovaní labelů může být na některých obrazovkách nudné, pomalé a úmorné, jsem si jist, že díky všem věcem zmíněným výše si ve výsledku spoustu času a frustrací ušetříme. Storyboards ale do budoucna nijak nezatracuji. Některé funkce (jako nedoladěný IBDesignable) jsou opravdu super a rád používám Storyboardy během výuky na ČVUT, kde je opravdu 100 × rychlejší naklikat GUI v IB, než ho psát v kódu. Stejně tak bych ho vždy použil na prototypování.
Nikdy neříkám nikdy, situaci kolem IB budu bedlivě sledovat, ale dokud se nevyřeší ty podle mě velice palčivé problémy (jestli je vůbec vyřešit lze), zůstanu věrný tvorbě GUI v kódu :)