Začínáme s AppKitem - 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:

Seriály

Více seriálů



Software

Začínáme s AppKitem

15. srpna 2005, 00.00 | Dnešním dílem našeho seriálu, věnovaného vývojovému prostředí Cocoa, se začneme zabývat programováním plnohodnotných aplikací s využitím objektové knihovny AppKit.

Dnešním dílem našeho seriálu, věnovaného vývojovému prostředí Cocoa, se začneme zabývat programováním plnohodnotných aplikací s využitím objektové knihovny AppKit (a také, v souvislosti s datovým modelem aplikací – viz. níže – si toho řekneme trochu více o jednom z nejnovějších subsystémů Cocoa, o Core Data). Knihovna AppKit nabízí třídy, funkce a další služby podobně, jako Foundation Kit, který již známe; zatímco Foundation obsahoval obecné třídy, vhodné pro libovolný program, v AppKitu jsou soustředěny třídy a služby potřebné právě pro plnohodnotné aplikace Mac OS X.

Aplikace je program, který nabízí standardní grafické uživatelské rozhraní, založené na oknech, nabídkách, myši a dalších prvcích rozhraní systému Mac OS X. Kromě toho aplikace musí dodržovat řadu systémových konvencí: obvykle podporuje služby typu schránky či Services, typicky nabízí standardní práci se soubory včetně služeb drag&drop, řada aplikací využívá standardní systém práce s dokumenty (včetně přiřazení typů dokumentů aplikaci) a podobně.

Všechny tyto služby zajišťují odpovídající třídy AppKitu. Vývojové prostředí Xcode navíc obsahuje standardní templates, díky nimž pro vytvoření základní aplikace, jež korektně dodržuje všechny konvence, nemusíme dělat téměř nic: třídy jsou automaticky sestaveny tak, jak je pro jednoduchou aplikaci zapotřebí, a Xcode nám vygeneruje i základní nejjednodušší grafické uživatelské rozhraní.

MVC

Dříve, než se pustíme do konkrétních služeb a tříd knihovny AppKit, je vhodné se trochu blíž věnovat obecné struktuře dobře navržené objektové aplikace: třídy a služby AppKitu totiž právě z této struktury vycházejí, a budeme-li jí rozumět a mít ji na paměti, budeme se v AppKitu (který je samozřejmě o dost složitější, než knihovna Foundation) lépe orientovat. Dnešní díl proto věnujeme obecným pravidlům objektového aplikačního designu typu "Model, View, Controller".

Jde o to, že základem kvalitního objektového designu je rozdělení aplikace na tři přinejmenším logicky nezávislé moduly: ty se tradičně nazývají "model" (representace dat, jež aplikace zpracovává), "view" (uživatelské rozhraní aplikace) a "controller" (správce, který váže "model" a "view" dohromady); pro aplikační strukturu, založenou na těchto třech modulech, se často používá zkratka složená z jejich prvních písmen: MVC.

Každý z modulů má jasně stanovenou úlohu:

  • Model representuje data, nad nimiž aplikace pracuje: obrázek, film, textový dokument, databázi (nebo, v tomto případě zvlášť vhodně pojmenovaný, databázový model), strukturu čísel a formulí pro spreadsheet... Aplikace samozřejmě může obsahovat modelů více, v závislosti na tom, s kolika "datovými bloky" pracuje;
  • View je pohled na model, který nabízí grafické uživatelské rozhraní. Podstatné a důležité z hlediska dobře navržené struktury aplikace je to, že samo grafické rozhraní neobsahuje ani vlastní data (to je úkolem modelu), ani logiku práce s nimi (o to se, jak hned uvidíme, stará Controller). Jednou z nejběžnějších a nejčastěji opakovaných chyb, při objektovém návrhu, jsou právě "views", obsahující data či řídící rutiny: tato chyba bývá běžná zvláště v prostředích, založených na C++. Modulů view (z nichž každý je samozřejmě obecně složen z řady objektů) může být v aplikaci obecně také více, neboť někdy zobrazujeme více různých údajů o modelu zároveň;
  • Controller stojí mezi modelem a "view", a zajišťuje logiku chování celého systému. Controller přijímá události, vyvolané vstupními objekty v rámci "view" (např. nabídkami, tlačítky a podobně); zpracuje je podle potřeby, a pak odpovídajícím způsobem upraví výstupní objekty v rámci "view" (textová pole, tabulky a další). Přitom samozřejmě podle potřeby spolupracuje s modelem — předává mu požadavky na změny, a kdykoli je to zapotřebí, vyžádá si od něj údaje pro zobrazení. V jednoduchých aplikacích bývá jeden controller, který "řídí vše"; v aplikacích, jež pracují s více nezávislými dokumenty, je obvykle jeden controller pro každý dokument. Složitější aplikace mohou mít controllerů řadu, každý z nich specializovaný na jinou část celkové funkčnosti.

Celou strukturu ilustruje následující obrázek:

Při návrhu, založeném na struktuře MVC, získáme nejvyšší flexibilitu a vícenásobnou použitelnost kódu: model není nijak závislý na konkrétní aplikační logice, můžeme jej beze změny a snadno využít v jakékoli jiné aplikaci, jež pracuje se shodnými daty. Podobně controller nijak nezávisí na konkrétním vzhledu grafického uživatelského rozhraní — to tak můžeme podle potřeby (a podle požadavků zákazníků) snadno měnit, aniž bychom museli zasahovat do kódu controlleru (natož pak modelu).

Triviální příklad

Pro lepší ilustraci si ukažme postavení jednotlivých objektů v hypotetické aplikaci, jež nedokáže nic jiného, nežli uchovat jediný textový řetězec (příště si ukážeme kompletní a mnohem dokonalejší aplikaci; dnes jde pouze o koncepci).

Model

Kód modelu bude zajišťovat načtení dat z nějakého vhodného místa pro permanentní uložení (dejme tomu, že aplikace používá defaults databázi); pro vyšší vrstvy pak nabídne triviální dvojici metod string a setString:, jež získají momentální hodnotu řetězce:

// model
-(NSString*)string {
  return [[NSUserDefaults sharedUserDefaults] stringForKey:@"string"];
}
-(void)setString:(NSString*)string {
  [[NSUserDefaults sharedUserDefaults] setObject:string forKey:@"string"];
}

To je celé. Model je za normálních okolností "pasivní", sám od sebe nic nedělá – jakékoli operace nad ním jsou vyvolány prostřednictvím zpráv, odeslaných z controlleru.

(Úmyslně na této úrovni zatím neřešíme, v rámci jaké třídy by byl kód modelu umístěn, a kde se vezme její instance: u takto triviální aplikace by totiž bylo nejrozumnější, aby model sdílel kód s controllerem, ovšem v obecném případě to samozřejmě dobře není. Praktičtější příklad si ukážeme příště.)

View

Objekty view, tedy grafického uživatelského rozhraní, jsou téměř vždy umístěny v souborech NIB, vytvářených a editovaných prostřednictvím aplikace InterfaceBuilder – my jsme se s ní již seznámili v minulých dílech, a v rámci popisu knihovny AppKit si o ní řekneme mnohem více.

Na této úrovni však stačí říci, že celým grafickým uživatelským rozhraním pro naši triviální aplikaci může být jediné okno, obsahující jediný objekt typu "textfield", zpřístupněný prostřednictvím "outletu" text. Není třeba vůbec nic programovat.

Controller

Kompletní controller bychom mohli také vytvořit bez jakéhokoli programování s využitím systému bindings (a v budoucích dílech to tak také budeme dělat); dnes si však ukážeme, jak by vypadal jeho kód v Objective C – jen proto, aby bylo zřejmé, co je přesně úkolem controlleru.

Je to, samozřejmě, velmi jednoduché – náš controller bychom umístili také do NIBu, a naprogramovali bychom v něm dvě metody (předpokládejme, že model je k dispozici v rámci proměnné model; jinak viz také poznámku na konci odstavce "Model"):

// controller
-(void)awakeFromNib {
  [text setStringValue:[model string]];
}
-(IBAction)textChanged:sender {
  [model setString:[text stringValue]];
}

To je celé: standardní metoda awakeFromNib zajistí, aby se po spuštění aplikaci zobrazila v textovém poli správná hodnota. Akce textChanged: – již samozřejmě v NIBu navážeme na "target" textového pole, aby ji systém po změně hodnoty v textovém poli automaticky zavolal – pak zajistí uložení nové hodnoty do modelu.

Postavení controlleru snad je tedy zřejmé: důležité je právě to, že textové pole i model nejsou nijak přímo spojeny, ale že tuto vazbu mezi zcela obecným textovým polem (jež lze použít na spoustu jiných věcí), a mezi zcela obecným datovým modelem (který může být zobrazen mnoha jinými způsoby) zajišťuje samostatný controller. Lze si třeba zajisté představit, že bychom naprogramovali podtřídu třídy NSTextField, a tak vytvořili textové pole, specializované jen a jen na zobrazování a editaci hodnoty "string" z modelu; to je ale právě špatný objektový design...

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

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Software  

 

 

 

Nejčtenější články
Nejlépe hodnocené články
Apple kurzy

 

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

Uživatelské jméno:

Heslo: