Programování na Macu - Aplikace pro kontrolu nové pošty (2) - 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ů



Informace

Programování na Macu - Aplikace pro kontrolu nové pošty (2)

7. prosince 2007, 09.00 | V minulém díle jsme založili nový projekt v Xcode a nakonfigurovali jej tak,

abychom mohli použít pro část kódu Javu. V tomto díle nejprve vyzkoušíme, jak

použití tříd napsaných v Javě funguje, a potom se vrátíme k uživatelskému

rozhraní a přidáme do lišty v pravém horním rohu svou ikonku a k ní menu.

Volání kódu v Javě

Zatím máme jen jednu prázdnou třídu v souboru Test.java. Otevřete tento soubor a přidejte do něj zvýrazněné řádky z následujícího výpisu:

public class Test {

    public void write(String msg) {
        System.out.println(msg);
    }

}

Přidaná metoda dostane jeden parametr typu String a vypíše jej na standardní výstup (v našem případě na konzolu Xcode).
Aby bylo možné třídu použít v Objective-C, musíme pro ni napsat rozhraní. Přidáme tedy soubor JavaInterfaces.h. Klikněte pravým tlačítkem na "Other Sources", vyberte "Add > New File..." a v okně položku "Empty File in Project". Do nového souboru nakopírujte tento kód:

@interface Test
{}
- (void)write:(NSString*)msg;
@end

Nyní bude při volání metody write z Objective-C jasné, jaké argumenty má dostat a jakého typu je návratová hodnota (resp. že metoda nic nevrací). Převod z typu NSString na javovský String probíhá automaticky, o to se starat nemusíme.
Teď otevřete soubor main.m a přidejte do něj zvýrazněné řádky:

#import <Cocoa/Cocoa.h>
#import "JavaInterfaces.h"

int main(int argc, char *argv[])
{
    Test* test = NSJavaObjectNamedInPath(@"Test", nil);
    [test write: @"Hello from Java"];
    return NSApplicationMain(argc,  (const char **) argv);
}

Po kliknutí na "Build and Go" se po kompilaci program spustí a v konzole byste měli vidět na posledním řádku text "Hello from Java". První řádek přidaného kódu vytvoří instanci třídy Test, druhý řádek zavolá její metodu write s jedním parametrem (v terminologii Objective-C bychom řekli, že jí předá zprávu). Jak již bylo uvedeno, argument typu NSString je před zavoláním metody převeden na typ v Javě, což se týká obecně všech základních typů a většiny tříd z frameworků Foundation a Application Kit (tj. tříd, jejichž jméno začíná prefixem NS).
Neděste se spousty varování v konzole. Ta se týkají správy paměti, konkrétně si systém stěžuje, že neexistuji žádný pool pro uvolňování paměti (autorelease pool). My budeme v budoucnu používat Javu až po inicializaci celé aplikace, kdy už bude k dispozici i korektní správa paměti.

Přidání ikonky a menu

A teď zpět k uživatelskému rozhraní.
  1. Klikněte dvakrát na položku MainMenu.nib. V Interface Builderu vyberte v hlavním okně záložku "Classes", klikněte na "NSObject" a stiskněte Enter. Tím jste vytvořili novou třídu, jejíž nadtřídou je NSObject, kterou pojmenujte AppController.

  1. V menu "Classes" vyberte "Instantiate AppController". Tím vytvoříte instanci této třídy, ke které budete mít přístup z kódu v Objective-C.
  2. V menu "Classes" vyberte "Create Files for AppController". Tento příkaz vygeneruje soubory AppController.h a AppController.m a přidá je do projektu.
  1. Vraťte se do Xcode a upravte soubory AppController.h a AppController.m.

// AppController.h

#import <Cocoa/Cocoa.h>


@interface AppController : NSObject
{
    NSStatusItem* statusItem;
}
- (NSMenu*)createMenu;
@end

Zde jsme nadefinovali vlastnost třídy statusItem, reprezentující položku horní lišty, a metodu createMenu, jež vytvoří nabídku naší aplikace.

// AppController.m

#import "AppController.h"


@implementation AppController
- (void)awakeFromNib {
    statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength: NSVariableStatusItemLength] retain];
    [statusItem setHighlightMode: YES];
    [statusItem setImage: [NSImage imageNamed: @"small"]];
    [statusItem setMenu: [self createMenu]];
}

- (NSMenu*)createMenu {
    NSMenu* menu = [[NSMenu alloc] initWithTitle: @"Email Notifier"];
   
    NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"Info..." action: @selector(about) keyEquivalent: @""];
    [item setTarget: self];
    [menu addItem: item];
   
    [menu addItem: [NSMenuItem separatorItem]];
   
    item = [[NSMenuItem alloc] initWithTitle: @"Quit" action: @selector(exit) keyEquivalent: @""];
    [item setTarget: self];
    [menu addItem: item];
   
    return menu;
}

- (void)dealloc {
    [statusItem release];
    [super dealloc];
}

- (void)about {
    [NSApp activateIgnoringOtherApps: YES];
    [NSApp orderFrontStandardAboutPanel: self];
}

- (void)exit {
    [NSApp terminate: nil];
}
@end

U této třídy se na chvilku zastavíme. Přidali jsme několik metod, které si zaslouží vysvětlení. Začneme od těch jednodušších:
  • Metoda exit ukončí aplikaci předáním zprávy terminate instanci NSApp.
  • Metoda about zobrazí dialog o naší aplikaci (což je ekvivalentní kliknutí na položku "About..." ve standardním menu programu).
  • Metoda dealloc uvolní paměť instance třídy AppController těsně před jejím zrušením.
  • Metoda awakeFromNib je zavolána po nahrání celého .nib souboru do paměti a instanci třídy AppController. My ji využíváme k přidání ikonky do lišty a vytvoření menu. Aby se ikonka zobrazila, musíte ji přidat do projektu. Klikněte na záložku "Resources", vyberte "Add > Existing Files..." a určete soubor s obrázkem, který  v liště bude reprezentovat vaši aplikaci. Soubor se musí jmenovat small, přípona závisí na typu souboru.
  • Metoda createMenu vytvoří objekt typu NSMenu s položkami Info... a Quit. První položka vyvolá metodu about a druhá metodu exit ve stejné třídě.
Nakonec ještě přidejte do souboru Info.plist následující dva řádky:

<key>NSUIElement</key>
<string>1</string>

To způsobí, že po spuštění aplikace se v docku nezobrazí její ikona ani hlavní menu, jak je pro tento typ programů obvyklé.
Kliknete-li nyní na "Build and Go", objeví se v horní liště ikonka s menu:
V dalším díle si ukážeme práci s modelem MVC (model-view-controller) a s objektovou databází.

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

 

Obávám se, že tudy cesta nevede!

Autor: OC Muž

Založeno: 07.12.2007, 14:31
Odpovědí: 0

Moment, Vy voláte Javu z ObjC? To bych neradil. Java bridge je zcela oficiálně \"deprecated\" -- touto cestou bych se tedy raději v nových aplikacích nevydával :)

Ona vůbec celá Java (přinejmenším v Mac OS X, ne-li již globálně) nemá moc světlou budoucnost. Bez ohledu na to, co je pravda \"objektivně\" (vizte ten flamewar u mého předminulého článku ;)), podstatné a určující tady je to, že ji nemá rád Steve:

Markoff: “And what are you thinking about Flash and Java?”
Jobs: “Java’s not worth building in. Nobody uses Java anymore. It’s this big heavyweight ball and chain.”

http://pogue
.blogs.nytimes.com/2007/0
1/13/ultimate-iphone-faqs
-list-part-2/

Doporuč
uji tedy pro Mac OS X raději programovat v ObjC. Nebo, máte-li proti němu nějaké zásadní výhrady, třeba v Ruby...

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

RE: Obávám se, že tudy cesta nevede!

Autor: PH Muž

Založeno: 07.12.2007, 14:46

Uvedený kód je myšlen jako návod, jak volat Javu z ObjC. V Javě existuje hodně užitečných knihoven a není důvod je nepoužívat, pokud to usnadní vývoj. Stav Javy v Cocoa je takový, že sice frameworky nejsou aktualizovány na novější verze, ale jinak se nic nemění. Takže volání Javy z ObjC nepředstavuje žádný problém.
Je logické, že píšu-li něco od nuly, použiju spíše ObjC, ale je-li možné použít hotový kód v Javě, je hloupost jej nevyužít, nebrání-li tomu nějaký závažný důvod (např. kdysi jsem přepisoval kód z Javy do C kvůli rychlosti a spotřebě paměti), ale to už je na jinou diskuzi.

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

RE: RE: Obávám se, že tudy cesta nevede!

Autor: OC Muž

Založeno: 07.12.2007, 15:02

No, samozřejmě, proti gustu není dišputace. Nicméně "deprecated" znamená, přeloženo do češtiny: "v některé z příštích versí systému to přestane fungovat".

Já bych v mých aplikacích takové věci nepoužíval, neboť preferuji, fungují-li (v maximální možné míře, např. teď mi Hacks samozřejmě v Le Prdu nechodí, jsouce Input Managerem :( ) i po upgrade, leč každému co jeho jest :)

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

RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: OC Muž

Založeno: 07.12.2007, 15:06

P.S. a pokud by tedy Java byla zapotřebí, udělal bych v ní raději samostatný tool a volal jej přes NSTask. Java jako taková (zatím :)) deprecated není, ale JavaBridge ano.

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

RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: PH Muž

Založeno: 07.12.2007, 15:10

Jistě, každý problém má více řešení.

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

RE: RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: OC Muž

Založeno: 07.12.2007, 15:36

Jistě, o tomto rozhodně nechci vést spor, cest je mnoho a všechny vedou do Říma ;)

Šlo mi jen o to, že podle mého soudu není vůbec rozumné učit lidi technologiím, jež Apple již označil jako "k vyhození" (tj. "deprecated").

Nebo alespoň, pokud ta technologie dejme tomu přináší takové výhody, že to i tak stojí za to, by bylo vhodné na to explicitně upozornit.

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

RE: Obávám se, že tudy cesta nevede!

Autor: black shadow Muž

Založeno: 10.12.2007, 11:26

jezis uz je to tu zase. a v cem ai tak programovat pro jiny system nez Mac OS X?

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

RE: RE: Obávám se, že tudy cesta nevede!

Autor: cca1 Muž

Založeno: 11.12.2007, 13:39

Suhlas:
Cocoa + Objective C je mozno najlesia kombinacia najlepsieho frameworku s najlepsim a najobjektovejsim jazykom, ale hranie sa na jednom piesocku a potom tazka portacia na iny piesocek patri do minulosti. Napisat UI cast pomocou Objective C a Interface Builderu, a na samotne kontrolery pouzit Javu je to minimum co by OS X mal umoznovat, ak je to uz mozne v Ruby a Pythone. Kludne by som sa uspokojil ak by sa dal lubovolny java class zavolat z objective C, najlepsie bez nutnosti byt odkazany na Apple, ci to laskavo bude umoznovat teraz alebo v buducnosti.

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

RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: hroch32 Muž

Založeno: 11.12.2007, 16:17

Jenže když použijete Cocoa + Java, tak je kompatibilita na stejné úrovni jako s ObjC. Prostě jste jen použil jiný jazyk nad stejným frameworkem. Ve chvíli, kdy to chcete portovat, tak musíte kompletně kód přepsat s využitím jiného frameworku. Neboli používat Javu v Cocoa je nesmysl. Pokud chcete použít Javu na multiplatformní programování, musíte použít i multiplatformní framework, což ale zase nebude to pravé ořechové.

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

RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: PH Muž

Založeno: 11.12.2007, 17:01

To už je lepší Cocoa+ObjC, protože pak se dát použít GNUstep (minimálně na Linuxu s ním mám dobré zkušenosti). Na Windows se dají pro jednodušší aplikace použít různé knihovny zabalující Winapi, které implementují části OpenStepu.

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

RE: RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: OC Muž

Založeno: 13.12.2007, 20:58

Ve Woknech GNUStep také chodil (před lety, když jsem to zkoušel) na úrovni engine velmi slušně, jen bylo potřeba instalovat něco jako Cyhnus kvůli toolům.

Stran otázky "v čem programovat pro jiné platformy", já bych to přeformuloval: *proč* vůbec programovat pro jiné platformy? Trh software pro Mac OS X je dost velký (přinejmenším nejde-li o specificky českou aplikaci, u nás je to bohužel slabší, takže např. korektor z ÚFALu má asi smolíka), a čím víc bude skvělých aplikací jen pro Maca a pro nic jiného, tím se dále bude zvětšovat.

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

RE: RE: RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: PH Muž

Založeno: 13.12.2007, 21:34

Korektor z ŮFALu/ÚJČ má výhradně Microsoft pro svůj Word, takže smůlu má Apple, resp. uživatelé Maců. Bohužel rozhraní v Cocoa (NSSpellServer) se stejně hodí maximálně pro kontrolu překlepů, na kontrolu gramatiky však zdaleka nestačí, resp. je absolutně nepoužitelné.

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

RE: RE: RE: RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: OC Muž

Založeno: 14.12.2007, 21:16

Já měl na mysli morfologický korektor, který v principu mohl být na trhu už dávno... podrobnosti např. tady:

http://www.okoun
.cz/boards/japka?contextI
d=5635022#article-5635022


Jinak stran rozhraní v Cocoa, vizte spellServer:checkGrammarI
nString:language:details: na straně serveru, checkGrammarOfString:star
tingAt:language:wrap:inSp
ellDocumentWithTag:detail
s: na straně checkeru. Nicméně zde máte bohužel naprostou pravdu v tom, že český gramatický korektor je (na rozdíl od morfologického, který by mohl na trh třeba hned, kdyby jej ovšem český trh dokázal zaplatit) zalicencovaný Microsoftem horem dolem :(

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

RE: RE: RE: RE: RE: RE: RE: RE: Obávám se, že tudy cesta nevede!

Autor: PH Muž

Založeno: 15.12.2007, 18:34

Tak to jsme si nerozuměli, morfologický korektor by samozřejmě v principu nebyl problém. Existují ostatně i jiné než z ÚFALu, možná by se vyplatilo se poptat (myslím, že jeden se jmenuje Ajka). Nouzově by možná stačilo vzít data z aspellu nebo ispellu a doplnit je o tokeny z ČNK.

To rozhraní pro kontrolu gramatiky je jen v Leopardu, že? Až mi konečně přijde Leopard update pro můj nový počítač (zakoupený před více než měsícem), tak to možná vyzkouším (ještě jsem se nerozhodl, zda ho vůbec budu instalovat, a na mé G4 1.5 GHz běží Xcode 3.0 dost pomalu).
Pokud se nepletu, mají to jen pro angličtinu (zkoušel jsem navíc jen němčinu a nic). Navíc to neopravuje gramatiku hned při psaní, to by chtělo vylepšit. Ale jinak je to krok správným směrem.

Myslím, že nějaký korektor gramatiky pro polštinu je k dispozici zdarma (nejspíše uzpůsobený pro OpenOffice). Syntaktická pravidla pro češtinu jsou dost podobná, takže úprava by nebyla nijak složitá. Jenže jednak nevím, jak dobrý ten polský korektor je, a navíc je pro to stejně nezbytné mít tu morfologii pro češtinu, takže asi fakt smůla.

Kdyby někdo náhodou věděl o nějaké (byť lexikálně omezené) morfologii zadarmo, šlo by s tím něco dělat, já mám pro OS X naimplementovanou gramatiku češtiny a slovenštiny v LFG (sice v Prologu, ale SWI Prolog běží na Macu velmi dobře a přepsat ta pravidla do ObjC by také nebyl moc velký problém).

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

Máte nápad na aplikaci pro iPhone?

Autor: Jan Beneš Muž

Založeno: 16.04.2009, 11:08

Máte zajímavý nápad na program pro iPhone? Můžeme zajistit jak vývoj, tak celý proces zajištění distribuce na AppStore a prodej. Samozřejmě většina výnosů a licence bude vaše! Dokonce můžeme vývoj předem uhradit za vás.

Pamatujte na to že trh s iPhony má nyní 17 milionů uživatelů kteří mohou platit kdekoli ťuknutím prstu.

Pokud nemyslíte objektově nebo jste dříve neprogramovali v C a nechcete investovat měsíce do učení, ani se do Objective-C nepouštějte, je to náročný jazyk.

Nápady můžete posílat na vyhodnocení na jan.benes@europm.com. Pokud si přejete, uzavřeme s vámi dohodu o utajení a prohlášení, že váš nápad zůstává vám.

Jan Beneš, EuroPM.

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

Ještě pár drobných technických...

Autor: OC Muž

Založeno: 07.12.2007, 14:58
Odpovědí: 0

A propos, jak to tak pročítám, ještě možná stojí za zmínku

- Neděste se spousty varování v konzole

Je samozřejmě otázka, zda to u takovéhoto rychlého testu stojí za to, nicméně medle je vhodné ta varování "vypnout" (to proto, abychom mezi nimi nepřehlédli nějaké jiné, jež by mohlo být důležité a indikovat skutečnou chybu -- tedy v principu z téhož důvodu, proč je správné nemít žádné compiler warnings).

To vypnutí je zcela triviální, stačí na začátek funkce main (resp. libovolné funkce, v níž se dělá něco dočasného z ObjC) přidat

[NSAutorelease
Pool new]

Alternativně, jste-li v Leopardu, lze aplikaci zbuildovat pro garbage collector, ale toto se mi jeví jednodušším :)

- V menu "Classes" vyberte "Instantiate AppController"

Ano, v Tygru ano. V Leopardu (resp. Xcode 3 a novém IB) je to _hodně_ jinak. Já to samozřejmě popíši v mém seriálu, ale kdy, to je otázka, neboť vychází cca jednou za měsíc :( (v RS už týdny leží asi tři dosud nevydané díly).

Aspoň v rychlosti pro ty, kdo už mají Xc3: je potřeba v Library vybrat modrou krychličku NSObject (nebo tak nějak, já teď mám přebootováno do Tygra a nemohu to ověřit), odvézt ji do okna NIBu, pak v Inspektoru v záložce Identity napsat jméno třídy ("AppCntroller").

Zdro
jáky je lepší napsat v Xcode rovnou. Chcete-li, nový IB je sice také vygenerovat umí (v menu někde -- Tools nebo tak -- najdete to vygenerování souborů), ale na rozdíl od starého IB to (a) nevytvoří nadtřídu, (b) nepřidá soubory do projektu. Medle to nestojí za to. Navíc nově napsané zdrojáky v Xcode3 nemusíte do IB přidávat, po jejich uložení si je načte automaticky.

- (void)awakeFromNib

na začátek je lepší přidat

if (statusItem) return;

V této jednoduché aplikaci je to jedno, ale budete-li ji časem rozšiřovat a přidáte nový NIB mohlo by se vám awake zavolat vícekrát, a pak byste se divil :)

- (NSMenu*)createMenu

Ch
ybí Vám tam autorelease, takže to menu leakne. Ono je to v praxi jedno, protože se to volá jen jednou, ale stejně je vhodné udržovat memory management korektní -- nebo takové věci aspoň komentovat ("//this leaks, we don't care, lives permanently").

Ostatn
generovat programově statické menu je vůbec donebevolající nesmysl (co třeba lokalizace?!?). Udělejte to menu pohodlně v Interface Builderu, přidejte si outlet, nadrátujte je na ten outlet, a v inicializaci statusitemu je rovnou použijte hotové.

- (void)dealloc

V kontrolleru je zbytečné, nikdy se nezavolá. Opět, na jeho psaní není nic špatného, ale může vést k chybě, když se necháte jeho existencí zmást a vložíte do něj něco, co by se _mělo_ stát před exitem aplikace. Nestane se to :)

Speciálně tedy Vaše tvrzení "Metoda dealloc uvolní paměť instance třídy AppController těsně před jejím zrušením" je na hranici mezi zavádějícím a nepravdivým -- to dealloc se prostě nikdy nezavolá (protože instance se nezruší, resp. je zrušena až spolu s celým procesem, a to už se žádné zprávy nepředávají).

Medle je proto lepší namísto deallocu do kontrolérů tohoto typu napsat jen komentář typu "//no dealloc: lives permanently".

- (void)exit

Pokud nechcete před ukončením dělat nějaké extra psí kusy, je lepší menu napojit přímo. Nejlépe v IB (jak jsem psal výše); nebo pokud programově, tak

item = [[NSMenuItem alloc] initWithTitle: @"Quit" action: @selector(terminate:) keyEquivalent: @""];
[item setTarget: NSApp];
[menu addItem: item];

A pokud ty psí kusy dělat chcete, stejně je na to lepší applicationWillTerminate: ;)

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

RE: Ještě pár drobných technických...

Autor: PH Muž

Založeno: 07.12.2007, 15:08

Když jsem to psal, Leopard ještě nebyl (dost dlouho to leželo v redakci).
A autorelease pool - ten ještě přijde... ;-) Feedback je vždy vítán, nicméně některé aspekty a vysvětlení jsem schválně nechal na další díly "miniseriálu" - to jen na vysvětlenou.

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

RE: RE: Ještě pár drobných technických...

Autor: OC Muž

Založeno: 07.12.2007, 15:33

> dost dlouho to leželo v redakci

Jojo, to znám :)

Především právě proto jsem to komentoval -- bůhvíkdy se Vám redakce uráčí vydat další díly, tak aby mezitím případní čtenáři začátečníci, kteří mají k dispozici jen toto a ne následující vysvětlení, darmo nenabrali nějaké zlozvyky...

Ono jinak samozřejmě cokoli je tak či onak diskutabilní; třeba to paradigma "co jde v IB, dělat v IB" (nejen menu, ale třeba různé obsahy dynamicky vytvářených tab views a podobně) je samozřejmě dvojsečné; ušetří to skutečně _spoustu_ práce dokud si člověk sám spravuje projekt, ale jakmile by mělo dojít na CVS a merge, je zaděláno na průšvih, protože obsah IB se (ani v textové podobě) nedá rozumně porovnávat a mergovat :(

A tak dále :)

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: