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:
Začínáme s
Druhé Objective C
29. listopadu 2007, 09.00 | Jak jsme si slíbili v minulém článku, v popisu novinek Leoparda začneme tím, co je nového v jazyce Objective C. Po velice dlouhé době, kdy – vyjma doplnění výjimek a synchronizace – nebylo nového nic, se toho tentokrát "urodilo" poměrně dost.
Jak jsme si slíbili v minulém článku, v popisu novinek Leoparda začneme tím, co je nového v jazyce Objective C. Po velice dlouhé době, kdy – vyjma doplnění výjimek a synchronizace – nebylo nového nic, se toho tentokrát "urodilo" poměrně dost. Pojďme si nejprve shrnout všechny novinky, jež se v Objective C objevily:
- podpora kritických sekcí v kódu a direktivy pro práci s výjimkami nejsou samy o sobě žádnou novinkou; přesto se na ně podíváme blíže ze dvou dobrých důvodů: předně, nové možnosti Objective C 2 ovlivňují jejich využití – a kromě toho stojí za to zdůraznit jeden potenciální problém s direktivou @finally, o němž jsme se v předcházejících dílech zapomněli zmínit;
- podpora garbage collectoru je na jazykové úrovni poměrně jednoduchá (složitý je samozřejmě runtime);
- možnost povolit přístupová práva k proměnným objektu pouze modulu, v němž je třída definována;
- možnost specifikovat dodatečné atributy pro metody a třídy pro vylepšení kontroly při překladu a pro lepší zapouzdření;
- možnost měnit kdykoli instanční proměnné objektu bez ohledu na podtřídy;
- rozšíření služeb protokolů a kategorií;
- nový příkaz pro iteraci objektů v cyklu;
- nová podpora pro deklarace a definice accesorů.
Kromě toho Objective C 2.0 v Leopardu nabízí řadu nových služeb pro dynamické zpracování zpráv; zastaralé a mnohdy nedostatečně flexibilní poseAsClass: nahrazuje novým mechanismem přímé záměny selektorů (tento mechanismus byl sice k dispozici i předtím, ale přístup k němu byl poměrně komplikovaný). To vše ale jsou věci, které se netýkají přímo vlastního jazyka, ale spíše podpory, již mu prostřednictvím služeb standardní třídy NSObject dává Foundation Kit; popíšeme si je proto až později, až od vlastního jazyka přejdeme k přehledu novinek v knihovnách.
Kritické sekce a výjimky
Jazyková podpora, kterou Objective C nabízí pro podporu kritických sekcí a výjimek, není nová; přesto však stojí za to se k ní vrátit, protože v Objective C 2.0 má některé nové vlastnosti (a také, jak jsme se již zmínili, v rámci našeho seriálu jsme na několik podstatných věcí zapomněli).
Kritické sekce
Podpora kritických sekcí je poměrně jednoduchá – my jsme se o ní zmínili v článku předem slibujícím Leopardí novinky, avšak nepopsali jsme si ji tehdy podrobně. Ačkoli tedy zrovna tato služba se od dob Tygra nikterak nezměnila (vizte ovšem poznámku k efektivitě zpracování výjimek na konci příštího odstavce), je nejvyšší čas tak učinit.
Podpora je založena na direktivě @synchronize, jež následující blok označí jako kritickou sekci:
@synchronize (zámek) { ... kritická sekce ... }
Objective C automaticky vygeneruje kód, který zajistí, aby kritickou sekci mohlo zpracovávat pouze jediné vlákno; pokud se k ní dostane zároveň jiné vlákno, je pozastaveno a na vstupu do kritické sekce čeká, dokud předchozí vlákno kritickou sekci neopustí.
Zámkem může být libovolný objekt (ve skutečnosti se zdá, že kód generovaný pro synchronizaci snese jakoukoli obecnou hodnotu a netrvá na tom, aby šlo právě o adresu objektu; není však samozřejmě dobré na to spoléhat, přinejmenším pro kompatibilitu s budoucími verzemi). Jeho funkcí je prostě a jednoduše rozlišit různé kritické sekce; kupříkladu tedy
@synchronize (pole1) { [pole1 addObject:o]; } @synchronize (pole2) { [pole2 addObject:o]; }
zajistí, že se více vláken zároveň nepokusí zapisovat do žádného z polí (v daném kódu samozřejmě), avšak nikterak nebude bránit jednomu vláknu v zápisu do pole1 a zároveň – vzhledem k odlišnému zámku – jinému vláknu v zápisu do pole2.
Kritická sekce je automaticky chráněna kódem pro zachycení výjimky; nemusíme se tedy obávat, že by výjimka uvnitř kritické sekce ponechala kritickou sekci uzamčenou. Tím se dostáváme ke druhé části:
Výjimky
Jazykové prostředky pro podporu výjimek Objective C 2.0 mění jen v jediné drobnosti, kterou popíšeme níže; významnější novinkou je to, že klasická makra NS_DURING/NS_HANDLER/NS_ENDHANDLER nyní nejenže jsou kompatibilní s výjimkami definovanými na úrovni jazyka; jsou přepsána přímo do direktiv @try/@catch, zhruba takto:
#define NS_DURING @try { #define NS_HANDLER } @catch (NSException *localException) { #define NS_ENDHANDLER } #define NS_VALUERETURN(v,t) return (v) #define NS_VOIDRETURN return
Další novinkou, jež se neprojeví přímo v jazyce, avšak může mít významné důsledky pro programátorský styl, je to, že firma Apple – pouze ovšem pro čtyřiašedesátibitové buildy! – změnila implementaci výjimek; nadále již nejsou založeny na službách setjmp/longjmp, ale využívají mechanismus výjimek C++. To má dva důsledky:
- výjimky C++ a Objective C jsou nyní navzájem kompatibilní; výjimka, vyvolaná vnořeným kódem C++, může být zachycena direktivou @catch v Objective C, a naopak;
- změnila se podstatným způsobem efektivita zpracování: průchod do bloku, chráněného direktivou @try, je nyní velmi efektivní; naopak je daleko "dražší" vyvolání výjimky direktivou @throw.
Prvý z důsledků souvisí s jedinou jazykovou změnou, kterou Objective C pro zpracování výjimek přináší: nyní lze v direktivě @catch použít argument "...", který zachytí skutečně cokoli, speciálně tedy neobjektovou výjimku C++ (a je možné ji předat do vyšší úrovně direktivou @throw bez argumentu).
Důsledkem druhého je určitá změna pohledu, jež velmi dobře souvisí s doporučením Apple výjimek užívat skutečně pouze pro výjimečné (chybové) stavy, a nikdy pro běžné zpracování dat: nestojí takřka nic ochranou @try/@catch opatřit téměř libovolný kód; naopak skutečného vyvolání výjimky bychom se měli vyvarovat, není-li to nutné.
Vzhledem k tomu, že – jak jsme si řekli v minulém odstavci – direktiva @synchronize pro vytvoření kritické sekce obsahuje implicitní ochranu @try/@catch, je to důležité i z hlediska kritických sekcí – ty můžeme používat bez obav o snížení efektivity kódu kdekoli, kde je to zapotřebí.
(Samozřejmě nevhodně umístěná kritická sekce stále může snížit efektivitu tím, že vlákna budou na vstup do ní čekat zbytečně; to je ale jiná otázka.)
Pozor na @finally!
V článku, v němž jsme se s jazykovou podporou pro práci s výjimkami seznámili, jsme uvedli (v podstatě, a k tomu s překlepem v názvu direktivy) tento příklad:
void *ptr=malloc(1000); @try { ... } @catch (NSObject *o) { @throw; // v pořádku: paměť se uvolní také } @finally { free(ptr); }
Ten je skutečně zcela v pořádku, vyplatí se však upozornit na nebezpečí, k němuž by mohla vést jeho příliš volná aplikace na jiné případy. Mnoho programátorů totiž jistě napadne, že s direktivou @finally je výhodný následující vzorec:
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; @try { ... } @finally { [pool release]; // POZOR, chyba! }
Výhodný není, naopak, je to cesta do pekel! Pro pochopení, proč tomu tak je, stačí si uvědomit, že direktivy @try/@catch/@finally automaticky předají každou výjimku, jež není explicitně zachycena některou z direktiv @catch, na vyšší úroveň kódu. Z toho ovšem plyne, že výjimka, vytvořená v době platnosti našeho lokální autorelease poolu – a tedy uložená právě do něj – se předá "výše", ale ještě před tímto předáním se pool v bloku @finally uvolní. Odkaz na výjimku tedy již v době jeho použití nebude platný!
Není-li to zřejmé, pomůže přepsat si situaci do "starých" maker:
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; NS_DURING ... [NSException exceptionWith:...] samozřejmě ... ... uloží výjimku do aktivního autorelease poolu ... NS_HANDLER [pool release]; // ekvivalent "finally", pool se uvolní [localException raise]; // toto udělá @try/@catch ... // ... automaticky pro každou nezachycenou výjimku; ... // ... zde ovšem jasně vidíme, že (a proč) ... // ... po uvolnění poolu localException není validní! NS_ENDHANDLER [pool release]; // ekvivalent "finally"
Nejjednodušším řešením výše popsaného problému je... se o autorelease pool prostě nijak nestarat. Jen ať si výjimka vyskočí ven; pool se uvolní automaticky díky poolu nadřízenému.
Obsah seriálu (více o seriálu):
- Nastal čas na kakao...
- Tak nejdřív kakao ochutnáme...
- Programovací jazyk C: velmi, velmi stručně
- Objective C: to si vysvětlíme podrobněji
- Co jsme si o Objective C ještě neřekli...
- Nastal čas na kakao - Vznik a zánik objektů
- Nastal čas na kakao - Kopírování objektů
- Nastal čas na kakao - Skryté podtřídy
- Nastal čas na kakao - Základní služby objektů
- Nastal čas na kakao - Jak správně psát v Objective C
- Nastal čas na kakao - Jak správně importovat
- Nastal čas na kakao - Podtřídy, delegáti, vkládání, jak se to rýmuje?
- Nastal čas na kakao - Využití kategorií namísto dědičnosti
- Nastal čas na kakao - Vkládání objektů a přesměrování zpráv
- Nastal čas na kakao - Inicializace a rušení objektů
- Nastal čas na kakao - Metody initWith... a designovaný inicializátor
- Nastal čas na kakao - Inicializace: tipy a triky
- Nastal čas na kakao - Accesory: přístup k proměnným instancí
- Nastal čas na kakao - Šedá je teorie, zelený je strom života...
- Nastal čas na kakao - Více o XCode: inspektory
- Nastal čas na kakao - Aplikace RSS2: datový model
- Nastal čas na kakao - Aplikace RSS: implementace datového modelu
- Nastal čas na kakao - Aplikace RSS: parsování XML
- Nastal čas na kakao - Interface Builder a uživatelské rozhraní
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Druhý kontrolér a dokončení aplikace
- Nastal čas na kakao - Drobná vylepšení a zdokonalení...
- Nastal čas na kakao - Ladění
- Nastal čas na kakao - Třídy Foundation Kitu
- Nastal čas na kakao - Třídy Foundation Kitu (2)
- Nastal čas na kakao - Textové řetězce: NS(Mutable)String
- Nastal čas na kakao - Čísla, binární data a další...
- Nastal čas na kakao - Archivace objektů
- Nastal čas na kakao - Trocha magie, aneb distribuované objekty
- Nastal čas na kakao - Málem bychom zapomněli: NSAutoreleasePool
- Nastal čas na kakao - Zpracování výjimek: NSException
- Nastal čas na kakao - NSInvocation a černá magie
- Nastal čas na kakao - Kakao v Tygrovi
- Nastal čas na kakao - Notifikace: nepřímé předávání zpráv
- Nastal čas na kakao - NSUserDefaults
- Nastal čas na kakao - Co nového ve Foundation Kitu
- Nastal čas na kakao – s Intelem, s Intelem, jedeme do...
- Co nového v Xcode
- Začínáme s AppKitem
- Jak MVC v Kakau vypadá doopravdy?
- Jak MVC v Kakau vypadá doopravdy: dokončení
- Přehled tříd AppKitu
- Nastal čas na kakao - Přehled tříd AppKitu 2
- Přehled tříd AppKitu 3: zbývající třídy GUI
- Přehled tříd AppKitu 4: textový systém
- Nastal čas na kakao - Přehled tříd AppKitu 5: hlavně grafika
- Přehled tříd AppKitu 6: dokumentový systém
- Přehled tříd AppKitu 7: dokončení
- Pojmenované vlastnosti objektů
- Pojmenované vlastnosti objektů: implementace
- Pojmenované vlastnosti objektů: relace 1:N
- Pojmenované vlastnosti objektů: řazení jmen a agregační funkce
- Sledování změn objektů
- Sledování změn objektů – ukázka
- Sledování změn objektů – zdrojový kód
- Sledování změn objektů: kód modelu
- Sledování změn objektů: přímý přístup
- Kontroléry a vazby
- Vázání vazeb
- Další vazby s jednoduchým kontrolérem
- Implementace a použití převodu hodnot
- Validace hodnot
- Validace a chyby, a jedna hezká vazba...
- Práce s polem objektů
- Základní vazby NSArrayControlleru
- Převodníky, přepínače, placeholdery
- Mírná vylepšení v mezích zákona
- Objective C 2.0 - novinky z Leoparda
- NSTreeController
- Programování v Cocoa - Pár tipů a triků
- Programování v Cocoa - Základy kreslení
- Kterak nakreslit modrý obdélník...
- Další služby pro kreslení
- Obrázky a písmenka...
- Události a myš
- Lepší práce s myší
- Události klávesnice
- Input Management
- Příkazy a schránka
- Další události
- Táhni a padni
- Byli jsme na tahu; nyní padneme.
- Zvolme si, jak vhodit
- Drobnosti a chybičky
- Speciální případy tahání či házení
- Kterak táhnout něco, co neexistuje?
- Jak na sítě...
- NSURLConnection
- Safari za minutu
- Služby WebKitu
- Kakao v Leopardu
- Druhé Objective C
- Druhé Objective C: různé drobnosti
- Druhé Objective C: kategorie a protokoly
- Druhé Objective C: nový příkaz cyklu
- Druhé Objective C: atributy a accesory
- Druhé Objective C: atributy a accesory
- 64 je dvakrát 32
- Ubicumque dulce est, ibi et acidum invenies...
- Irbis: že prý žádné novinky?
- Blok sem, blok tam, nám už je to všechno jasné...
- Bloky jsou i v AppKitu
- Irbis a Foundation Kit
- Kde jsou má data?
- Kde jsou má data? V NSCache!
- Soubor, jméno, URL, jak se to rýmuje...
- Další podpora NSURL
- Zabíjení!
- A máme tady i...OS!
- Systémové prvky GUI
- Programování pro iOS 1. díl - Rozdíly mezi "i" a "Mac"
- Programování pro iOS - 2. Začínáme programovat
- Programování pro iOS - 3. základní ovladače a propojení GUI s kódem
- Programování pro iOS - 4. Varovná hlášení
- Programování pro iOS - 5. Rámce a jejich řídicí objekty
- Programování pro iOS - 6. Ukládání dat
- Programování pro iOS - 7. Správa paměti a starý restík
- Programování pro iOS - 8. Dokončení aplikace
- Programování pro iOS - 9. Jak dostat aplikaci do iPhone
- Programování pro iOS - 10. Instalace aplikace do cizího iPhone
- Programování pro iOS - 11. Jak dostat aplikaci do libovolného iPhone
- Programování pro iOS - 12. Touching!
- Programování pro iOS - 13. Kreslíme na iPhone
- Programování pro iOS - 14. Udělejme gesto
- Programování pro iOS - 15. Další gesta
- Programování pro iOS - 16. Více prstů, více zábavy
- Programování pro iOS - 17. Podpora standardních gest
- Programování pro iOS - 18. Recognizery v iOS
- Programování pro iOS - 19. Další standardní recognizery
- Programování pro iOS - 20. Co nového v iOSu
- Programování pro iOS - 21. "Multitasking"
- Programování pro iOS - 22. Nulla est honesta avaritia nisi temporis
- Programování pro iOS - 23. Jak se aktivovat, jsme-li v pozadí
- Programování pro iOS - 24. Zbývající drobnosti
- Programování pro iOS - 25. Řídicí objekty rámců
- Programování pro iOS - 26. Jak se dělá UIViewController
- Programování pro iOS - 27. Kde vzít rámce
- Programování pro iOS - 28. Základní služby
- Programování pro iOS - 29. Práce s rámci
- Programování pro iOS - 30. Rotace zařízení
- Programování pro iOS - 31. Správa paměti v rámcích
- Programování pro iOS - 32. Řídicí objekt pro tabulky
- Programování pro iOS - 33. Řídicí objekt pro strom
- Programování pro iOS - 33. Více o UINavigationControlleru
- Programování pro iOS - 35. Ještě jednou UINavigationController
- Programování pro iOS - 36. Po navigátoru taby
- Programování pro iOS - 37. Více o UITabBarControlleru
- Programování pro iOS - 38. Dokončení UITabBarControlleru
- Programování pro iOS - 39. UIPopoverController
- Programování pro iOS - 40. Další triky UIPopoverControlleru
- Programování pro iOS - 41. Zbývající služby UIPopoverControlleru
- Programování pro iOS - 42. UISplitViewController
- Programujeme v
iTunesXcode 4 - Programování pro iOS - 44. Předvolby Xcode 4
- Programování pro iOS - 45. Práce v Xcode 4
- Xcode 4: projekt a cíle
- Xcode 4: práce s cíli
- Xcode 4: Build Settings
- Xcode 4: Build Phases
- Xcode4: Build Phases podruhé
- Xcode 4: Co jsou to Build Rules?
- Xcode4: taje editoru
- Xcode4: automatické doplňování v editoru
- XIBy chyby
- Více o XIBech
- Editor XIBů
- Inspektory pro XIBy
- Vazby mezi objekty v XIBech
- Vazby mezi objekty v kódu
- Paletky Xcode pro XIBy
- Xcode 4: levý sloupec
- Xcode 4: okno Organizer
- Xcode 4: okno Organizer, část druhá
- Xcode 4: co je to Workspace?
- Xcode 4: základy schémat
- Xcode 4: akční schémata
Tématické zařazení:
» Rubriky » Začínáme s