Jak MVC v Kakau vypadá doopravdy: dokončení - 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ů



Software

Jak MVC v Kakau vypadá doopravdy: dokončení

9. září 2005, 00.00 | V předcházejícím dílu našeho seriálu jsme začali s jednoduchou ukázkovou aplikací, na níž zhruba vidíme, jak se s MVC – modely, view objekty a kontroléry – ve skutečnosti v Cocoa pracuje. Dnes aplikaci dokončíme: na řadě teď je tedy samozřejmě view a kontrolér.

V předcházejícím dílu našeho seriálu jsme začali s jednoduchou ukázkovou aplikací, na níž zhruba vidíme, jak se s MVC – modely, view objekty a kontroléry – ve skutečnosti v Cocoa pracuje: připravili jsme projekt a sestavili jsme datový model pro velmi jednoduchou účetní aplikaci (jež dokáže pouze udržovat seznam několika účtů a na každém z nich seznam transakcí).

Dnes aplikaci dokončíme: na řadě teď je tedy samozřejmě view a kontrolér. V Xcode je obvykle sestavujeme najednou – view pomocí standardních tříd, representujících objekty GUI (NSView pro okno, NSTextField pro textové pole a podobně); controller s využitím systému "bindings" a jeho standardních tříd (NSController a její dědicové). Pro obojí nabízí své služby jediná aplikace – Interface Builder; jakkoli tento přístup z koncepčního hlediska je možná malinko nešťastný (protože trochu zastírá zřejmé rozhraní mezi "view" a "controllerem", a protože oba ukládá do téhož "zdrojového" souboru, totiž do NIBu), v praxi je velmi šikovný. Umožňuje totiž průběžné sestavování grafického uživatelského rozhraní zároveň s určováním vazeb do modelu; to je daleko pohodlnější (a rychlejší), než kdybychom to dělali v samostatných krocích ve dvou různých aplikacích.

Navíc, jak si hned ukážeme, jednotlivé subsystémy v Xcode dokáží spolupracovat, takže ani nemusíme všechny potřebné prvky view a kontroléru vytvářet jeden po druhém ručně – Interface Builder dokáže na základě informací z modelu vytvořit standardní sestavu view a odpovídajícího kontroléru, již pak můžeme jen podle potřeby mírně upravit (jde zhruba o něco podobného, jako když nám v minulém dílu Xcode automaticky vygenerovalo standardní kód pro načítání a ukládání dat, v němž jsme jen změnili jméno cílové složky).

Standardní GUI a kontrolér pro zvolenou entitu

Interface Builder tedy automaticky dokáže vytvořit plně funkční grafické uživatelské rozhraní pro přístup k údajům dané entity. Postup, jímž si to od něj můžeme vyžádat, je jednoduchý:

  • otevřeme soubor "MainMenu.nib" (je standardně uložen ve skupině "Resources"). To spustí Interface Builder a zobrazí obsah standardně vygenerovaného aplikačního GUI, tj. hlavní menu a jedno – prozatím prázdné – okno (a několik dalších pomocných objektů, jimž se budeme věnovat až později);
  • opět otevřeme v Xcode model a v jeho dolní části, v níž je model zobrazen jako graf vzájemně propojených entit (podívejte se na obrázek v minulém dílu), vyhledáme požadovanou entitu (tj. Account)...;
  • ... přidržíme přepínač ⌥ a entitu vhodíme do okna aplikace v Interface Builderu. Ten se optá, zda má generovat grafické uživatelské rozhraní pro jeden objekt nebo pro více objektů dané entity; zvolíme druhou variantu ("many objects").

To je celé: Interface Builder vloží do hlavního okna sestavu, obsahující tabulku s předdefinovanými sloupci pro oba atributy z entity Account (bank a number), vyhledávací textové pole, umožňující obsah tabulky dynamicky filtrovat, několik tlačítek pro znovunačtení dat z disku, přidání nového řádku a jeho zrušení, a textová pole pro případnou editaci řádků již existujících.

To vše jsou objekty view; zároveň se v okně, representující vlastní soubor NIB, objevil nový kontrolér (Interface Builder automaticky zvolí vhodnou třídu pro tento objekt; jelikož jsme se rozhodli pro "many objects", půjde o instanci třídy NSArrayController). Automaticky jsou i připraveny všechny potřebné vazby, jež kontrolér spojují s modelem – taková vazba je ostatně jen jediná, chceme-li si ji zkontrolovat, vidíme ji na následujícím obrázku; jde o vazbu atributu managedObjectContext kontroléru na kód, který pro nás vygeneroval už systém Xcode (můžete se samozřejmě podívat do generovaného zdrojového kódu jak přesně metoda managedObjectContext – jejíž volání je předepsáno v políčku "Model Key Path" na následujícím obrázku – vypadá, ale zatím, dokud jsme se podrobně nezabývali službami tříd knihovny Core Data, nebude kód asi příliš srozumitelný):

Důležitější je, že Interface Builder pro nás automaticky sestavil i všechny potřebné vazby mezi view a kontrolérem; to nám ušetří spoustu práce, neboť zde samozřejmě musí být samostatná vazba pro každý samostatný objekt v grafickém uživatelském rozhraní: svou vazbu má každý sloupec tabulky, každé textové pole, a korektně jsou na kontrolér navázána i tlačítka (u nich se systém "bindings" používá jen pro automatickou deaktivaci tlačítek, jež v dané situaci nemají smysl – např. deaktivaci "Remove" není-li v tabulce nic vybráno; pro vlastní funkci tlačítek slouží standardní mechanismus target/action, a ten pro nás Interface Builder na služby kontroléru navázal také).

Stačí tedy, upravíme-li objekty view jen natolik, nakolik chceme mít vzhled aplikace odlišný od standardně vygenerovaného rozložení: asi budeme chtít vzájemně prohodit sloupce tabulky, umístit tlačítka a textová pole vpravo od tabulky, a zrušit vyhledávání – účtů bude těžko kdy tolik, aby mezi nimi vyhledávání mělo smysl. Výsledek by mohl vypadat třeba takto:

Pokud nyní aplikaci v Xcode zbuildujeme a spustíme, bude již plně funkční a budeme moci v "databázi" vytvářet, rušit a editovat účty. Samozřejmě můžeme grafické uživatelské rozhraní "spustit" i přímo v Interface Builderu; z něj však samozřejmě nebudeme mít možnost pracovat s daty, neboť sice má k dispozici plnohodnotné objekty view i kontrolér, jenže mu schází kód, který je součástí projektu a který se právě stará o načtení dat z disku a jejich zpětné uložení (a který pro nás vygeneroval Xcode, takže jsme jej nemuseli psát).

Druhá entita a vazba master/detail

Nyní do okna vhodíme druhou entitu, Transaction; opět si vyžádáme vytvoření GUI a kontroléru pro "many objects". Interface Builder samozřejmě opět automaticky vytvoří všechny potřebné objekty i vazby mezi nimi, stejně jako v minulém případě; grafické uživatelské rozhraní zase trochu upravíme. Změny se tentokrát budou týkat především toho, že v tabulce zrušíme sloupec account a také vyhodíme odpovídající rozevírací nabídku.

Interface Builder totiž samozřejmě vytvořil view a kontrolér tak, abychom mohli pracovat se všemi datovými objekty entity Transaction, a pro každý z nich nezávisle na ostatních vidět a určovat jeho relaci do entity Account – prostě řečeno, kterému účtu daná transakce patří.

My ale chceme, aby se aplikace chovala trochu jinak: v tabulce transakcí chceme vidět pouze ty, jež patří vybranému účtu v tabulce účtů; přidáme-li transakci, chceme, aby se automaticky přiřadila vybranému účtu. Zvolíme-li v horní tabulce jiný účet, chceme, aby se obsah dolní tabulky ihned změnil (a zobrazil sadu transakcí právě vybraného účtu). Tomuto typu grafického uživatelského rozhraní se říká "master/detail" a jeho nastavení si ukážeme za chvilku – prozatím jen zrušíme ty view objekty, jež slouží k editaci relace mezi transakcemi a účty:

Nyní nastavíme požadovanou funkci "master/detail". Je zřejmé, že půjde o záležitost kontroléru, nikoli view – objekty grafického uživatelského rozhraní "nevědí", jaká data a kdy zobrazují; je úkolem kontrolérů jim je (z modelu) zprostředkovat.

Vybereme tedy v hlavním okně, representující soubor NIB kontrolér, který řídí zobrazení objektů entity Transaction – půjde samozřejmě o další objekt třídy NSArrayController, který nám Interface Builder automaticky vygeneroval po vhození entity do okna. Přepneme inspektor atributů objektu do režimu "Bindings" a určíme, že "obsah" kontroléru – tedy jeho atribut contentSet – má být navázán na seznam transakcí v právě zvoleném objektu účet. Tedy – v kontroléru účtů "Key" selection (zvolený objekt), "Model Key Path" transactions (relace téhož jména v entitě Account):

Nu, a to je vlastně vše: nyní již aplikace bez obtíží funguje – můžeme ji zbuildovat, spustit a vyzkoušet. Můžeme podle potřeby vytvářet i rušit účty a transakce, a naše rozhraní typu "master/detail" funguje korektně – kdykoli v horní tabulce nějaký účet vybereme, v dolní se hned zobrazí jeho transakce.

Díky rozumnému využití standardních kontrolérů a jejich služeb funguje i řada dalších drobností: samozřejmě, že obsah tabulky transakcí můžeme filtrovat pomocí vyhledávacího pole. Můžeme také klepnout na titulek kteréhokoli sloupce v kterékoli tabulce, a tabulka se přetřídí podle hodnot tohoto sloupce...

Přibližně takto to vypadá u každé aplikace

Samozřejmě, že v praxi při tvorbě skutečných aplikací se neobejdeme docela bez psaní zdrojového kódu v Objective C, jako tomu bylo v tomto příkladu (ve skutečnosti vlastně také tak úplně nebylo; nějaký zdrojový kód jsme potřebovali, jenže jsme jej nemuseli psát sami, neboť jej pro nás vygeneroval Xcode z projektového vzoru).

Důležité však je, že základní koncepce MVC jako takového i jeho representace prostřednictvím služeb knihovních tříd Cocoa se nemění.

V praxi obvykle rozšíříme služby entit modelu o další možnosti, jež explicitně naprogramujeme – nebo dokonce ani nevyužijeme systém Core Data a sestavíme celý model "ručně". V praxi obvykle rozšíříme služby kontrolérů o naše vlastní funkce a metody. Někdy – byť zdaleka ne v každé aplikaci – dokonce doplňujeme i vlastní objekty view, jež nabízejí bohatší nebo nadstandardní služby grafického uživatelského rozhraní. Na celkové struktuře aplikace a na základním postupu jejího sestavení, jež jsme si minule a dnes ukázali, to ale nic nemění.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Software  

Diskuse k článku

 

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

 

To je kouzelne

Autor: Tomas Muž

Založeno: 10.09.2005, 13:25
Odpovědí: 0

Kdyby to psal nekdo jiny, tak bych tomu asi ani neveril. Takhle jsem si to vyzkousel a ono to vazne funguje. Ted zvazuji, jestli se mam na stara kolena jeste poustet do Objective C. Diky. ;-) BTW je nejaka nadeje, byt jen vyhledove, ze by se takto "vytvoreny" program dal zkompilovat a spustit pod GNUstepem?

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

Co "transakce"?

Autor: zoul Muž

Založeno: 11.09.2005, 20:18
Odpovědí: 0

Vyvoj pro Macky soukam do hlavy teprve nedlouho a docela zesiroka, tak doufam, ze nebudu se svym dotazem mimo.

Chci jednoduche rozhrani s tabulkou, jen master/detail nechci mit implementovane jako cast okna, ale jako samostatny dialog. Uzivatel poklepe na radek tabulky, vyskoci dialog, uzivatel upravi co chce. Co kdyz ale misto OK klikne na Cancel? Pokud to dobre chapu, pri uprave hodnot v dialogu dochazi skrz bindings automaticky k uprave promennych objektu. Jde nejak zaridit "transakcni zpracovani" uprav? Tj. vyplnuju, vyplnuju, vyplnuju a pak bud klik na OK a commit uprav objektu nebo klik na Cancel a rollback uprav?

Diky, T.

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

Uz to mam

Autor: zoul Muž

Založeno: 12.09.2005, 12:56

http://www.cocoabuilder.c
om/archive/message/cocoa/
2005/6/18/139257

...kd
yby to nekoho zajimalo.

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: