K vašim službám 4: vyhrazeno pro programátory - 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

K vašim službám 4: vyhrazeno pro programátory

macos_prax_1k

11. prosince 2001, 07.00 | Všechny podstatné informace o tom, co systém Services nabízí uživatelům, jsme probrali v minulých dílech. Tentokrát se pro změnu na služby podíváme z druhé strany: jak je naprogramovat? Ideální pro zájmce o programování v Cocoa API

Všechny podstatné informace o tom, co systém Services nabízí uživatelům, jsme probrali v minulých dílech. Tentokrát se pro změnu na služby podíváme z druhé strany: jak je naprogramovat?

Začneme tím nejjednodušším: jak psát aplikace, které služeb využívají.

Vždyť by to mělo jít samo?!?

Pozorný čtenář se možná zarazil: o čem se vůbec máme bavit, když — jak jsme si řekli hned na začátku — framework Cocoa zajišťuje přístup k využití služeb automaticky?

Inu, budeme se bavit o tom, co automatické není a být nemůže. Je pravda, že kdekoli v Cocoa použijeme standardní systémový prvek, který pracuje s textem (textové pole v dialogu, textový editor v okně, tabulku, která umožňuje editaci políček,...), skutečně už se nemusíme starat doslova o nic: služby prostě fungují.

Jiná věc ale je, chceme-li služby nabídnout nějakým nestandardním způsobem, specifickým jen pro danou aplikaci: máme třeba takovouto tabulku:

Samozřejmě, že Cocoa se postará o to, že kdykoli některé z políček tabulky editujeme, Services automaticky fungují; my bychom však chtěli více: kdykoli je jen označen některý řádek tabulky (jako na obrázku), měly by být k dispozici textové služby nad jménem, které je v něm zobrazeno (na obrázku tedy "A.C."). Takovou službu samozřejmě Cocoa automaticky zajistit nemůže — musíme se o to postarat sami. Hned uvidíme, že to není nic těžkého.

Principy...

Podpora využití služeb má tři jednoduché kroky:

  1. na začátku se aplikace zaregistruje se všemi datovými typy, nad nimiž má pro ni smysl vůbec Services využívat. Podle toho se sestaví menu Services: jestliže např. aplikace pro služby nenabízí datový typ "soubor", nebudou souborové služby v menu Services v dané aplikaci vůbec obsaženy;
  2. kdykoli je to zapotřebí (např. když uživatel otevře menu Services), systém se zeptá aktivního objektu (viz níže), jaká data právě teď může službám nabídnout;
  3. je-li některá služba spuštěna, systém si nabídnutá data skutečně vyžádá.

Za trochu podrobnější zmínku stojí "aktivní objekt": na základní úrovni, na které se nyní pohybujeme, jde o ten objekt, se kterým právě uživatel přímo pracuje (obvykle "do kterého naposledy klepl myší"). Cocoa ovšem nabízí nesmírně propracovaný systém, který umožní objektům se podle potřeby navzájem zastupovat, tzv. "responder chain"; jeho podrobnější popis by však přesáhl rámec tohoto článku.

...a jejich konkrétní využití

Pro zajištění tří bodů z minulého odstavce musíme implementovat tři metody. Ačkoli máme dlouhou řadu nejrůznějších možností (mj. i s využitím "responder chainu", který nám umožňuje implementovat tyto metody jako součást řady různých objektů), zvolíme tu nejjednodušší: v rámci tzv. kategorie doplníme metody přímo do knihovní implementace třídy NSTableView, jež representuje tabulku:

@implementation NSTableView (TableSelectionServiceByNameCategory)
-(void)awakeFromNib {
    [NSApp registerServicesMenuSendTypes:[NSArray arrayWithObject:NSStringPboardType]
        returnTypes:nil];
}
-(id)validRequestorForSendType:(NSString*)sendType returnType:(NSString*)returnType {
    if ([sendType isEqual:NSStringPboardType] && [self selectedRow]>=0)
        return self;
    return nil;
}
-(BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard types:(NSArray*)types {
    if ([types containsObject:NSStringPboardType] && [self selectedRow]>=0) {
        NSString *value=[[self dataSource] tableView:self
            objectValueForTableColumn:[self tableColumnWithIdentifier:@"name"]
            row:[self selectedRow]];
        [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
        return [pboard setString:value forType:NSStringPboardType];
    }
    return NO;
}
@end

Metoda awakeFromNib slouží pro inicializaci GUI objektů; my v jejím rámci prostřednictvím standardní služby registerServicesMenuSendTypes:returnTypes: dáme systému na vědomí, že nás zajímají jen ty Services, které pracují nad textovými daty (NSStringPboardType), a nic nevracejí. Pole (NSArray) se zde používá proto, že obvykle bývá datových typů více.

Na základě této registrace se systém naší aplikace při otevření menu Services vždy "zeptá" prostřednictvím služby validRequestorForSendType:returnType:, zda pro danou službu máme nějaká data k dispozici. Implementace je triviální: pokud jde skutečně o textová data (NSStringPboardType), a pokud je nějaký řádek tabulky označen ("[self selectedRow]>=0"), vrátíme objekt, který data na požádání dodá (self). Jinak hodnota nil říká, že momentálně žádná data nejsou k dispozici (takže systém odpovídající položku menu Services zobrazí šedě).

Pokud služba validRequestorForSendType:returnType: nicméně vrátila nějaký objekt, je odpovídající položka menu v Services aktivní; pokud ji uživatel zvolí, systém objektu zašle zprávu writeSelectionToPasteboard:types:. I její implementace je triviální:

  1. pro jistotu (vlastně je to zbytečné, ale tzv. defensivní programování se vždy vyplatí!) ověříme, zda mezi datovými typy, o které má příjemce zájem, jsou opravdu textová data ("[types containsObject:NSStringPboardType]"), a zda je opravdu některý řádek tabulky označen;
  2. příkaz "value=..." zde nemůžeme vysvětlovat podrobně; vychází však přímo z API tabulky: žádáme zdroj dat, jež tabulka zobrazuje, aby nám dal text ze sloupce s identifikátorem "name" a z označeného řádku;
  3. službou declareTypes: jen potvrdíme, že odesíláme opravdu textový řetězec (v našem případě tomu jinak ani být nemohlo, ale obecně se např. často rozhodujeme mezi odesláním obyčejného a formátovaného textu);
  4. konečně, služba setString:forType: řetězec fakticky uloží do sdílené oblasti, odkud si jej spolupracující aplikace vyzvedne.

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

 

Opravte prosím čitelnost

Autor: Roman Petrla Muž

Založeno: 01.03.2006, 12:57
Odpovědí: 0

v novém designu. Ale aspoň jsem otestoval services a posílal si označený text do TextEditu:-)

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: