Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
02809 011073 14443956 na godz. na dobę w sumie
Objective-C. Leksykon profesjonalisty - książka
Objective-C. Leksykon profesjonalisty - książka
Autor: Liczba stron: 240
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-4350-9 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie mobilne >> iphone
Porównaj ceny (książka, ebook, audiobook).

Objective-C to nowoczesny język programowania, dzięki któremu możesz tworzyć zaawansowane aplikacje dla produktów ze stajni Apple. Produkty takie, jak iPad, iPhone czy laptopy z systemem operacyjnym MacOS, podbiły serca użytkowników na całym świecie. Co ważne, ich pozycja wydaje się niezagrożona! Dlatego inwestycja w wiedzę na temat tego języka jest w pełni uzasadniona.

Z tą książką błyskawicznie poznasz możliwości języka Objective-C. Dzięki przystępnemu wprowadzeniu zapoznasz się z podstawami języka, a w kolejnych rozdziałach poszerzysz wiedzę o bardziej zaawansowane zagadnienia. Podręcznik wypełniony ponad setką listingów z kodem źródłowym programów sprawi, że będziesz mógł stworzyć działający kod w języku Objective-C praktycznie w każdej sytuacji. W trakcie lektury dowiesz się, jak zarządzać pamięcią, korzystać ze wzorców oraz wykonywać operacje na ciągach znaków, liczbach i kolekcjach. Ponadto sprawdzisz, jak w Objective-C korzystać z plików, wątków i dostępu do sieci. Poświęć chwilę tej książce, a już wkrótce zaczniesz tworzyć zaawansowane oprogramowanie w Objective-C!

Sprawdź:

Twój przewodnik do pierwszej aplikacji w Objective-C!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

• Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis treĴci Rozdziađ 1. Rozdziađ 2. O autorze ..........................................................................9 Podziõkowania ...............................................................11 Wprowadzenie ...............................................................13 Filozofia Objective-C .....................................................15 Model obiektowy ................................................................................... 15 OpowieĞü o dwóch systemach typów .................................................... 17 C to Objective-C .................................................................................... 17 JĊzyk i biblioteka ................................................................................... 18 Historia Objective-C .............................................................................. 20 WieloplatformowoĞü ............................................................................. 22 Kompilowanie programów napisanych w Objective-C ......................... 23 Elementarz Objective-C ................................................25 Deklarowanie typów w Objective-C ..................................................... 26 Wysyáanie wiadomoĞci .......................................................................... 28 Selektory ............................................................................................... 30 Deklarowanie klas ................................................................................. 31 Protokoáy ............................................................................................... 35 Dodawanie metod do istniejącej klasy ................................................... 36 Nieformalne protokoáy .......................................................................... 38 Generowanie metod przy uĪyciu zadeklarowanych wáaĞciwoĞci .......... 38 Sáowa kluczowe self, _cmd i super ........................................................ 42 WskaĨnik isa ......................................................................................... 44 Inicjalizowanie klas ............................................................................... 46 Kodowanie typów .................................................................................. 47 UĪywanie bloków .................................................................................. 49 4 Spis treħci Rozdziađ 3. Zarzádzanie pamiõciá ..................................................51 Zajmowanie i zwalnianie pamiĊci ......................................................... 51 Przypisywanie do zmiennych instancyjnych ......................................... 52 Automatyczne zliczanie referencji ........................................................ 53 Zwracanie obiektów przez argumenty bĊdące wskaĨnikami ................. 54 Unikanie cykli pozyskanych referencji .................................................. 56 Migracja do ARC .................................................................................. 57 Pule automatycznego zwalniania pamiĊci ............................................. 59 Konstruktory automatycznie zwalniające pamiĊü .................................. 61 Automatyczne zwalnianie obiektów w akcesorach ............................... 61 Wsparcie dla automatycznego odĞmiecania kolekcji ............................. 62 Wspóápraca z C ..................................................................................... 64 Niszczenie obiektów .............................................................................. 65 Sáabe referencje ..................................................................................... 66 Alokowanie skanowanej pamiĊci .......................................................... 68 Rozdziađ 4. Najwaŏniejsze wzorce w Objective-C .........................71 Dwufazowe tworzenie obiektów ........................................................... 71 Kopiowanie obiektów ............................................................................ 72 Archiwizowanie obiektów ..................................................................... 74 Tworzenie wyznaczonych inicjalizatorów ............................................. 76 Singleton ............................................................................................... 77 Delegowanie .......................................................................................... 79 Budowanie fasad ................................................................................... 80 Tworzenie klastrów klas ........................................................................ 81 PĊtla wykonania .................................................................................... 83 Liczby ..............................................................................85 Przechowywanie liczb w kolekcjach ..................................................... 86 Arytmetyka liczb dziesiĊtnych .............................................................. 88 Konwersje miĊdzy ciągami znakowymi i liczbami ............................... 90 Odczytywanie liczb z ciągów znakowych ............................................. 91 Rozdziađ 6. Operacje na ciágach znakowych ...............................93 Tworzenie staáych ciągów znakowych .................................................. 94 Porównywanie ciągów znakowych ........................................................ 94 Przetwarzanie ciągu znakowego litera po literze ................................... 96 Zmiana kodowania ciągów znakowych ................................................. 98 Przycinanie ciągów znakowych ........................................................... 100 Dzielenie ciągów znakowych .............................................................. 101 Kopiowanie ciągów znakowych .......................................................... 101 Tworzenie ciągów znakowych z szablonów ........................................ 103 Dopasowywanie wzorców do ciągów znakowych ............................... 105 Przechowywanie tekstu z formatowaniem ........................................... 106 Rozdziađ 5. Spis treħci 5 Rozdziađ 9. Rozdziađ 7. Kolekcje ........................................................................109 UĪywanie tablic ................................................................................... 110 Kontrolowanie indeksów ..................................................................... 111 Przechowywanie nieuporządkowanych grup obiektów ....................... 112 Tworzenie sáownika ............................................................................ 113 Iterowanie po kolekcji ......................................................................... 114 Wyszukiwanie obiektu w kolekcji ....................................................... 116 Dziedziczenie z kolekcji ...................................................................... 118 Przechowywanie obiektów Objective-C w kolekcjach C++ ................ 120 Rozdziađ 8. Data i czas ....................................................................123 Odczytywanie aktualnej daty ............................................................... 123 Przygotowanie dat do wyĞwietlenia .................................................... 124 Zliczanie upáywającego czasu ............................................................. 126 Odczytywanie dat z ciągów znakowych .............................................. 126 Zdarzenia stopera ................................................................................ 127 Listy węaĴciwoĴci ..........................................................129 Przechowywanie kolekcji w listach wáaĞciwoĞci ................................. 130 Odczytywanie danych z listy wáaĞciwoĞci ........................................... 131 Zmiana formatu list wáaĞciwoĞci ......................................................... 133 JSON ................................................................................................... 134 Przechowywanie ustawieĔ ................................................................... 135 Przechowywanie dowolnych obiektów w systemie ustawieĔ .............. 138 Rozdziađ 10. Interakcja ze Ĵrodowiskiem ........................................141 Pobieranie wartoĞci Ğrodowiskowych .................................................. 141 Przetwarzanie argumentów z linii komend .......................................... 142 Ustawienia regionalne uĪytkownika .................................................... 144 Nagáe zakoĔczenie programu .............................................................. 145 Rozdziađ 11. Kodowanie klucz-wartoĴã ..........................................147 DostĊp do wartoĞci poprzez klucz ....................................................... 147 Uzyskiwanie zgodnoĞci z KVC ........................................................... 148 ĝcieĪki do klucza ................................................................................. 151 Obserwowanie kluczy ......................................................................... 152 Uzyskiwanie zgodnoĞci z KVO ........................................................... 153 Rozdziađ 12. Obsęuga bęõdów ..........................................................155 RóĪnice w implementacji wyjątków .................................................... 156 Rzucanie i áapanie wyjątków ............................................................... 157 Obiekty wyjątków ............................................................................... 159 Zunifikowany model wyjątków ........................................................... 160 Wyjątki a zarządzanie pamiĊcią .......................................................... 161 Przekazywanie delegat z báĊdami ........................................................ 162 Zwracanie informacji o báĊdzie ........................................................... 163 NSError ............................................................................................... 164 6 Spis treħci Rozdziađ 13. Dostõp do katalogów i plików ....................................167 Odczytywanie pliku ............................................................................. 167 Przenoszenie i kopiowanie plików ...................................................... 169 Pobieranie atrybutów pliku .................................................................. 170 Modyfikacja ĞcieĪek ............................................................................ 171 Sprawdzanie, czy plik lub katalog istnieje ........................................... 172 Praca z pakietami ................................................................................. 173 Odszukiwanie plików w lokacjach systemowych ................................ 175 Rozdziađ 14. Wátki .............................................................................179 Tworzenie wątków .............................................................................. 179 Ustawianie priorytetu wątku ................................................................ 180 Synchronizowanie wątków .................................................................. 182 Przechowywanie danych specyficznych dla danego wątku ................. 183 Oczekiwanie na prawdziwoĞü warunku ............................................... 185 Rozdziađ 15. Bloki i Grand Central ...................................................189 Wiązanie zmiennych z blokami ........................................................... 189 Zarządzanie pamiĊcią a bloki .............................................................. 192 Wykonywanie czynnoĞci w tle ............................................................ 194 Tworzenie wáasnych kolejek pracy ..................................................... 196 Rozdziađ 16. Powiadomienia ............................................................199 ĩądanie powiadomieĔ ......................................................................... 199 Wysyáanie powiadomieĔ ..................................................................... 201 Kolejkowanie powiadomieĔ ................................................................ 201 Przesyáanie powiadomieĔ miĊdzy aplikacjami .................................... 202 Rozdziađ 17. Sieã ................................................................................205 Wykorzystywanie obudowanych socketów z jĊzyka C ....................... 205 àączenie siĊ z serwerami ..................................................................... 207 Przesyáanie obiektów przez sieü .......................................................... 208 Wyszukiwanie wĊzáów równolegáych ................................................. 210 Wczytywanie danych spod adresu URL .............................................. 212 Rozdziađ 18. Debugowanie Objective-C ........................................215 Inspekcja obiektów .............................................................................. 215 Rozpoznawanie problemów z pamiĊcią .............................................. 217 Obserwowanie wyjątków .................................................................... 218 Asercje ................................................................................................. 220 Zapisywanie wiadomoĞci o báĊdach .................................................... 221 Spis treħci 7 Rozdziađ 19. ijrodowisko uruchomieniowe Objective-C ...............223 Wysyáanie wiadomoĞci na podstawie nazwy ....................................... 223 Odszukiwanie klas wedáug nazwy ....................................................... 224 Sprawdzanie, czy obiekt posiada daną metodĊ .................................... 225 Przekierowywanie wiadomoĞci ........................................................... 227 Odszukiwanie klas ............................................................................... 228 Inspekcja klas ...................................................................................... 229 Tworzenie nowych klas ....................................................................... 231 Dodawanie nowych zmiennych instancyjnych .................................... 232 Skorowidz ......................................................................235 8 Spis treħci Rozdziađ 3. Zarzádzanie pamiõciá JeĞli pochodzisz ze Ğrodowiska programistów C lub C++, prawdopodobnie we krwi masz Ğledzenie wáasnoĞci obiektów oraz rĊczne alokowanie ich i niszczenie. JeĞli pochodzisz ze Ğrodowiska programistów jĊzyków podobnych do Javy, przywy- káeĞ do automatycznego odĞmiecacza pamiĊci, który wykonuje tĊ pracĊ za Ciebie. Objective-C na poziomie jĊzyka nie pozwala na alokacjĊ lub dealokacjĊ obiek- tów. Jest to pozostawione kodowi napisanemu w C. Alokacja obiektów nastĊpuje zwykle po wysáaniu do ich klasy wiadomoĞci +alloc, która z kolei wywoáuje metodĊ malloc() lub podobną, by zarezerwowaü pamiĊü na obiekt. Wysáanie obiektowi wia- domoĞci –dealloc czyĞci i usuwa jego zmienne instancyjne. Framework Foundation rozbudowuje to proste, rĊczne zarządzanie pamiĊcią o zlicza- nie referencji. Gdy tylko zrozumiesz, jak dziaáa, Twoje Īycie stanie siĊ prostsze. Nowsze kompilatory pomogą Ci, zdejmując z Ciebie trud pisania kodu zliczającego referencje. Zajmowanie i zwalnianie pamiõci 6 NSArray *anArray = [NSArray array]; 7 anArray = [[NSArray alloc] init]; 8 [anArray release]; Z pliku: retainRelease.m Z kaĪdym obiektem dziedziczącym z NSObject jest powiązany licznik referencji. Gdy osiągnie wartoĞü 0, obiekt jest niszczony. Obiekt utworzony przy uĪyciu +alloc lub podobnej metody, jak np. +new czy +allocWithZone:, rozpoczyna swój Īywot z licznikiem ustawionym na wartoĞü jeden. 52 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ Licznik referencji obiektu moĪna kontrolowaü, wysyáając mu wiadomoĞci –retain i -release. Jak wskazują ich nazwy, wykorzystuje siĊ je do pozyskiwania referencji na obiekt lub jej zwalniania. WiadomoĞü –retain inkrementuje licznik referencji, a wiadomoĞü –release go dekrementuje. By okreĞliü obecny stan licznika referencji, wyĞlij wiadomoĞü –retainCount. Kuszące moĪe byü optymalizowanie kodu, polegające na wykorzystaniu specjalnego przy- padku, gdy istnieje tylko jedna referencja na obiekt. Jest to bardzo záy pomysá. Jak sama nazwa wskazuje, metoda zwraca liczbĊ jawnie pozyskanych referencji, a nie referencji w ogóle. Podczas tworzenia na stosie wskaĨnika do obiektu po- wszechne jest niezawracanie sobie gáowy wysyáaniem do niego wiadomoĞci –retain. W efekcie do obiektu mogą prowadziü dwie lub wiĊcej referencji, choü licznik jest ustawiony na jeden. WskaĨniki w Objective-C są podzielone na dwie kategorie: referencje wáasno- Ğciowe i referencje niewáasnoĞciowe. Referencja wáasnoĞciowa to taka, która modyfikuje licznik referencji obiektu. Wywoáując metody takie jak +new lub –retain, otrzymuje siĊ referencjĊ wáasnoĞciową do nowego obiektu. WiĊkszoĞü pozosta- áych metod zwraca referencje niewáasnoĞciowe. Zmienne instancyjne i globalne są przewaĪnie wskaĨnikami wáasnoĞciowymi, wiĊc powinno siĊ im przypisaü re- ferencje wáasnoĞciowe. Trzeba takĪe upewniü siĊ, Īe przed przypisaniem nowej referencji wáasnoĞciowej usuniĊto starą (wysyáając wiadomoĞü –release). Zmienne tymczasowe są zwykle referencjami niewáasnoĞciowymi. Automatyczne zliczanie referencji i odĞmiecanie pamiĊci, którym przyjrzymy siĊ w dalszej czĊĞci obecnego rozdziaáu, wprowadzają specjalne rodzaje tego typu referencji. Przypisywanie do zmiennych instancyjnych 26 - (void)setStringValue: (NSString*)aString 27 { 28 id tmp = [aString retain]; 29 [string release]; 30 string = tmp; 31 } Z pliku: ivar.m Jest kilka rzeczy, na które trzeba uwaĪaü podczas korzystania ze zliczania referencji. RozwaĪmy taką oto prostą metodĊ ustawiającą: Automatyczne zliczanie referencji 53 14 - (void)setStringValue: (NSString*)aString 15 { 16 [string release]; 17 string = [aString retain]; 18 } Z pliku: ivar.m Kod wygląda rozsądnie. Zwalniana jest referencja do starej wartoĞci, po czym pozy- skiwana i przypisywana jest nowa wartoĞü. Zwykle kod bĊdzie dziaáaá, ale w kilku przypadkach zawiedzie. Czyni to debugowanie go zajĊciem niezwykle trudnym. Co stanie siĊ, jeĞli wartoĞü aString i string bĊdą takie same? W tym przypadku wyĞlesz jednemu obiektowi wiadomoĞü –release, a nastĊpnie –retain. O ile inny kod utrzyma referencjĊ do obiektu, wszystko zadziaáa poprawnie, ale jeĞli nie, to pierwsza wiadomoĞü spowoduje zniszczenie obiektu, a druga zostanie wysáana do „wiszącego” wskaĨnika. Na początku rozdziaáu pokazano lepszą implementacjĊ, która najpierw pozyskuje referencjĊ do nowego obiektu. Zwróü uwagĊ, Īe powinieneĞ zachowaü wartoĞü zwracaną z wiadomoĞci –retain, bo niektóre obiekty zwrócą inny obiekt, gdy je pozyskasz. To bardzo rzadkie zachowanie, ale wystĊpuje raz na jakiĞ czas. W koĔcu metoda nie jest bezpieczna ze wzglĊdu na wątki. JeĞli chcesz, by taką byáa, musisz zarezerwowaü nowy obiekt, wykonaü niepodzielną operacjĊ podmiany go i zmiennej instancyjnej, a nastĊpnie zwolniü starą wartoĞü. Jest to fatalny po- mysá, bo ciĊĪko objąü rozumem kod, który zawiera tak duĪo drobiazgowej obsáugi wspóábieĪnoĞci, a iloĞü zmarnowanego cache’u przewyĪszy zyski z równolegáego wykonania. JeĞli naprawdĊ potrzebujesz równolegáego wykonania, lepiej uĪyj zade- klarowanych wáaĞciwoĞci do wygenerowania akcesoria, zamiast pisaü go rĊcznie. Automatyczne zliczanie referencji Wraz z wydaniem iOS 5 i Mac OS X 10.7 firma Apple wprowadziáa automa- tyczne zliczanie referencji (Automatic Reference Counting — ARC). Koncep- cyjnie polega to na tym, Īe kompilator sam decyduje, kiedy powinien wywoáaü –retain oraz –release, i robi to za Ciebie. Rzeczywista implementacja jest oczy- wiĞcie nieco bardziej skomplikowana. Zamiast wstawiaü bezpoĞrednio do kodu wysyáanie wiadomoĞci, kompilator wstawia wywoáania funkcji takich jak objc_retain() i objc_release(). NastĊpnie opty- malizator stara siĊ poáączyü lub wyeliminowaü te wywoáania. W prostym przypadku funkcje wykonują pracĊ analogiczną do wysyáanych wiadomoĞci. Jednak w niektó- rych przypadkach są znacznie bardziej efektywne. 54 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ WiökszoĈè przykäadów w tej ksiñĔce korzysta z röcznego zliczania referencji. Jest to celowe. Pomimo Ĕe stosowanie ARC jest zalecane w nowych projektach, istnieje duĔo starego kodu, który z niego nie korzysta. Nawet jeĈli wykorzystujesz ARC, wciñĔ powinieneĈ rozumieè istotö wykonywanego za Ciebie pozyskiwania i zwalniania referencji. Podobnie warto znaè zestaw instrukcji procesora, nawet jeĈli nigdy nie pisze siö kodu w asemblerze. ProgramiĈcie, który rozumie röczne zliczanie referencji, bardzo äatwo jest przestawiè siö na zliczanie automatyczne. W prostych zastosowaniach wykorzystanie ARC pozwala zapomnieü o zarządzaniu pamiĊcią. JeĞli uĪywasz nowej wersji Ğrodowiska XCode, ARC jest rozwiązaniem domyĞlnym. JeĞli kompilujesz z linii komend lub przy uĪyciu jednego z innych systemów budowania projektów, dodaj opcjĊ –fobjc-arc. Teraz wystarczy tylko zapomnieü o koniecznoĞci pozyskiwania i zwalniania referencji. Byáoby wspaniale, gdyby Īycie byáo tak proste. Niestety ARC ma pewne ogranicze- nia. Mówiąc konkretniej, formalizuje mĊtną granicĊ miĊdzy pamiĊcią C a obiek- tami Objective-C, dzieląc wskaĨniki na trzy kategorie. Silne wskaĨniki pozyskują i zwalniają pamiĊü tak, jak widzieliĞmy wczeĞniej. Sáabe, którym przyjrzymy siĊ póĨniej, to niewáasnoĞciowe referencje zerowane automatycznie podczas niszczenia obiektu. Ostatnią grupĊ stanowią niebezpieczne, niepozyskane wskaĨniki. Są ignoro- wane przez ARC: sam jesteĞ odpowiedzialny za czas Īycia przechowywanych w nich obiektów. DomyĞlnie wszystkie wskaĨniki w zmiennych instancyjnych i na stosie są mocne. WskaĨniki na obiekty w strukturach nie mają wartoĞci domyĞlnej i muszą byü jawnie oznaczone kwalifikatorem __unsafe_unretained. Mimo Īe w ich przypadku jest to jedyne dozwolone prawo wáasnoĞci, trzeba go jawnie uĪyü, by przypo- mnieü osobom czytającym kod, Īe wskaĨniki te bĊdą ignorowane przez ARC. Zwracanie obiektów przez argumenty bõdáce wskaōnikami 3 __weak id weak; 4 int writeBack(id *aValue) 5 { 6 *aValue = [NSObject new]; 7 weak = *aValue; 8 return 0; 9 } 10 11 int main(void) 12 { Zwracanie obiektów przez argumenty búdæce wskaļnikami 55 13 @autoreleasepool 14 { 15 id object; 16 writeBack( object); 17 NSLog(@ Obiekt: @ , object); 18 object = nil; 19 NSLog(@ Obiekt: @ , weak); 20 } 21 NSLog(@ Obiekt: @ , weak); 22 return 0; 23 } Z pliku: writeback.m W trybie ARC argumenty bĊdące wskaĨnikami do wskaĨników dziaáają w dosyü skomplikowany sposób. Ich zastosowanie obejmuje zwykle dwa przypadki: prze- kazywanie tablic lub zwracanie obiektów. JeĞli przekazujesz tablicĊ w dóá stosu, to powinieneĞ upewniü siĊ, Īe zadeklarowaáeĞ ją jako const. Informuje to kompi- lator, Īe wywoáywana funkcja nie przypisze niczego do tablicy, wiĊc ARC bĊdzie mógá przekazaü ją bez Īadnej skomplikowanej interwencji. JeĞli poprzez argumenty bĊdące wskaĨnikami bĊdziesz zwracaá obiekt, to ARC utworzy dosyü skomplikowany kod. W przykáadzie z początku tego podrozdziaáu wywoáanie writeBack() generuje kod zbliĪony do tego: id tmp = [object retain]; writeBack( tmp); [tmp retain]; [object release]; object = tmp; W funkcji writeBack() nowy obiekt bĊdzie automatycznie usuniĊty z pamiĊci przed przechowaniem go w tymczasowej wartoĞci. Oznacza to, Īe na koĔcu tego procesu object zawiera wáasnoĞciową referencjĊ do nowego obiektu. JeĞli zadeklarowaáeĞ object jako _autoreleasing id, wygenerowany kod jest znacznie prostszy. Automatycznie zwalnia wartoĞü przechowywaną początkowo w object, co nie bĊdzie miaáo Īadnego efektu, bo wartoĞcią początkową wszystkich wskaĨników — nawet tych przydzielanych automatycznie — i tak jest nil, a na- stĊpnie bezpoĞrednio przekazuje wskaĨnik i oczekuje, Īe jeĞli wywoáywana funkcja go zmodyfikuje, to umieĞci na jego miejsce wskaĨnik niewáasnoĞciowy (automa- tycznie zwalniany). 56 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ JeĞli uruchomisz ten przykáad, to zobaczysz, Īe sáaba referencja jest zerowana wyáącznie, gdy niszczona jest pula automatycznego przydziaáu. We wszystkich przypadkach funkcja writeBack() przechowuje zwolniony automatycznie obiekt w przekazanym wskaĨniku i nigdy nie usuwa z pamiĊci przekazanej wartoĞci. Wywoáujący jest zawsze odpowiedzialny za upewnienie siĊ, Īe do funkcji prze- kazuje referencjĊ niewáasnoĞciową, co czyni na jeden z dwóch sposobów: albo upewnia siĊ, Īe wskaĨnik pokazuje na automatycznie zwalniany obiekt, albo Īe jest kopią wskaĨnika na obiekt, dla którego pozyskano referencjĊ. JeĞli zamiast tego oznaczysz parametr sáowem out (dozwolone wyáącznie w przypad- ku parametrów metod, a nie funkcji C), to wywoáywana metoda gwarantuje, Īe nie odczyta tej wartoĞci. Kompilator bĊdzie mógá wiĊc pominąü krok, w którym wykonuje kopiĊ wskaĨnika przechowywanego w object przed wywoáaniem. JeĞli musisz przekazaü kilka obiektów w górĊ stosu, to powinieneĞ prawdopodobnie zwróciü instancjĊ NSArray. Jest kilka alternatyw, ale są wystarczająco záoĪone, by nie byáy warte wysiáku: korzystając z nich, áatwo popeániü maáy báąd i spĊdziü wieki na debugowaniu kodu. Nawet jeĞli uda Ci siĊ zrobiü wszystko dobrze, przypusz- czalnie i tak metody te bĊdą wolniejsze niĪ uĪycie NSArray. JeĞli przekazujesz kilka wartoĞci w dóá stosu, to powinieneĞ zadeklarowaü typ tablicy z jawnym kwalifikatorem wáasnoĞci dla parametru, a nie typ wskaĨnikowy. Na przykáad __unsafe_unretained id[] zamiast id*. Zapewnia to wyáączenie mechanizmu zapisu zwrotnego. Unikanie cykli pozyskanych referencji 19 - (void)setDelegate: (id)aDelegate 20 { 21 delegate = aDelegate; 22 } Z pliku: ivar.m Problemem w przypadku „czystego” zliczania referencji jest to, Īe nie wykrywa cykli. JeĞli dwa obiekty przechowują referencje do siebie nawzajem, Īaden z nich nie zostanie nigdy zwolniony. Generalnie nie jest to wielki problem. Struktury danych w Objective-C są zwykle acykliczne, ale istnieją przypadki, w których cykle są nieuniknione. Najpopularniej- szym z nich jest wzorzec delegacji. Wzorzec polega na tym, Īe jeden obiekt imple- mentuje jakiĞ mechanizm, ale zarządzanie pracą przekazuje innemu obiektowi. WiĊkszoĞü frameworku AppKit dziaáa w ten sposób. Migracja do ARC 57 Obiekty potrzebują do siebie nawzajem referencji, co momentalnie tworzy cykl. Popularnym sposobem rozwiązania problemu jest przyjĊcie zasady, Īe obiekty nie pozyskują na siebie referencji. JeĞli przekaĪesz obiekt jako argument do metody –setDelegate:, bĊdziesz musiaá upewniü siĊ, Īe referencja jest przechowywana przez jakiĞ inny obiekt lub Īe zostanie przedwczeĞnie zwolniona, a obiekt usuniĊty. W przypadku ARC masz dwie moĪliwoĞci: moĪesz oznaczyü zmienną instancyjną sáowem __weak albo __unsafe_unretained. Pierwsza z opcji jest bezpieczniejsza, bo zapewnia, Īe wskaĨnik nie bĊdzie „wisiaá w powietrzu”. Gdy delagata zostanie zniszczona, zmienna instancyjna zostanie ustawiona na nil. Są dwie wady uĪywania sáabych wskaĨników. Pierwszą jest przenoĞnoĞü. Sáabe wskaĨniki dziaáają na iOS 5, Mac OS X 10.7 i w GNUstep, ale nie dziaáają na starszych wersjach iOS i Mac OS X. Drugą wadą jest wydajnoĞü. W kaĪdej próbie dostĊpu do wskaĨnika poĞredniczy funkcja pomocnicza, sprawdzająca, czy obiekt nie jest w stanie dealokacji, i pozyskująca referencjĊ do niego, jeĞli jest wciąĪ „Īywy”, albo zwracająca nil w przeciwnym przypadku. Pod nazwą niebezpiecznych, niepozyskanych wskaĨników kryją siĊ zwykáe, „tra- dycyjne” wskaĨniki, oferujące tani dostĊp do obiektu i dziaáające na kaĪdej plat- formie sprzĊtowej. Ich wadą jest obarczanie uĪytkownika odpowiedzialnoĞcią za upewnienie siĊ, Īe po zwolnieniu wskazywanego obiektu uĪytkownik nie siĊgnie juĪ wiĊcej do wskaĨnika. Dobrym kompromisem jest uĪywanie sáabych wskaĨników w trakcie debugowa- nia i niebezpiecznych, niepozyskanych wskaĨników w trakcie normalnej pracy. Dodaj asercjĊ sprawdzającą, czy wskaĨnik nie jest równy nil, przed wysáaniem mu jakiejkolwiek wiadomoĞci, a jeĞli bĊdziesz miaá báĊdy, to skoĔczysz z uĪytecznym komunikatem zamiast nagáego przerwania aplikacji. Migracja do ARC JeĞli zaczynasz nowy projekt w XCode, ARC bĊdzie domyĞlnym wyborem i ciĊĪko znaleĨü powody, by z niego nie skorzystaü. JeĞli jednak pracujesz ze starszym ko- dem, prawdopodobnie bĊdziesz uĪywaá rĊcznego zliczania referencji. W dáugiej perspektywie moĪna oszczĊdziü sobie pracy, przenosząc kod do ARC, ale jest to nieco trudniejsze niĪ ustawienie przeáącznika kompilacji. Clang posiada narzĊdzie wspomagające migracjĊ, które próbuje przepisaü kod Objective-C tak, by korzystaá z ARC. Wywoáuje siĊ je z linii komend przy uĪyciu ar- gumentów –ccc-arcmt-check i –ccc-arcmt-modify. Pierwszy z nich informuje o wszystkich miejscach w kodzie, które nie mogą byü automatycznie zmienione. O ile nie bĊdzie báĊdów, drugi wykona konwersjĊ kodu, modyfikując oryginalny plik. 58 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ W prostym kodzie Objective-C narzĊdzie zadziaáa poprawnie. Najbardziej oczy- wistymi zmianami bĊdzie usuniĊcie wszystkich wiadomoĞci –retain, –release i autorelease. NarzĊdzie usunie takĪe jawne wywoáanie [super dealloc] z metody –dealloc. Od teraz wywoáanie jest wstawiane automatycznie przez kompilator. ARC automatycznie zwalnia wszystkie zmienne instancyjne, wiĊc metodĊ –dealloc bĊdziesz musiaá zaimplementowaü, tylko jeĞli musisz zwolniü pamiĊü zajĊtą przez funkcjĊ malloc() lub podobne konstrukcje. JeĞli utworzyáeĞ wáasne metody do zliczania referencji, bĊdziesz musiaá je usunąü. Popularnym powodem wáasnej implementacji jest chĊü unikniĊcia przypadkowego usuniĊcia singletonów. Traci to na znaczeniu w przypadku ARC, poniewaĪ báąd programisty ma mniejsze szanse na spowodowanie przedwczesnego usuniĊcia obiektu. Do zwalniania zmiennych instancyjnych ARC tworzy metodö –.cxx_ destruct. Metoda ta byäa pierwotnie utworzona, by po zniszczeniu obiektu automatycznie wywoäywaè destruktory z C++. Widocznñ róĔ- nicñ pomiödzy jej dawnym zastosowaniem a ARC w Objective-C jest to, Ĕe zmienne instancyjne sñ teraz dealokowane po wykonaniu funkcji –dealloc w klasie-korzeniu, a nie przed. W wiökszoĈci przypadków nie powinno mieè to znaczenia. NajwiĊksze problemy pojawiają siĊ, jeĞli próbujesz przechowaü wskaĨniki Ob- jective-C w strukturach C. Najprostszym rozwiązaniem jest po prostu nierobienie tego. W zamian uĪyj obiektów Objective-C z publicznymi zmiennymi instancyjnymi. Pozwoli to kompilatorowi zająü siĊ zarządzaniem pamiĊcią obiektu i jego pól. Jedynym przypadkiem, w którym uznaje siĊ, Īe uĪywanie struktur odnoszących siĊ do obiektów Objective-C jest bezpieczne, jest sytuacja, gdy przekazujesz je w dóá stosu. WskaĨniki na obiekty mogą posiadaü kwalifikator __unsafe_unretained tak dáugo, jak dáugo pozostają poprawne w funkcji, w której powstaáy. Po uĪyciu narzĊdzia do migracji zauwaĪysz, Īe zniknĊáy wáaĞciwoĞci assign. Zostaáy one przepisane jako unsafe_unretained lub weak, w zaleĪnoĞci od tego, czy wy- brana platforma docelowa kompilacji obsáuguje sáabe referencje. JeĞli wáaĞciwoĞci assign wykorzystywaáeĞ do przerywania prostych cykli i uznasz, Īe sáabe referencje stwarzają problemy wydajnoĞciowe, moĪesz jawnie zmieniü niektóre z nich na unsafe_unretained. NarzĊdzie do migracji spróbuje w odpowiednich miejscach powstawiaü rzutowanie mostkowane __bridge, ale warto sprawdziü, czy zrobiáo to poprawnie. Rzutowania te są wykorzystywane do dodawania i usuwania obiektów z kodu zarządzanego przez ARC. W kodzie niewykorzystującym ARC moĪna korzystaü z konstrukcji ta- kich jak (void*)someObject, bo wskaĨniki na obiekty są zwykáymi wskaĨnikami C, Pule automatycznego zwalniania pamiúci 59 do których dodatkowo moĪna wysyáaü wiadomoĞci. W trybie ARC rzutowanie byáoby wieloznaczne, bo kompilator nie wiedziaáby, która zmienna ma byü wáaĞci- cielem obiektu wskazywanego przez void*. Z tego powodu taki kod jest zabroniony. NarzĊdzie do migracji przepisze przedstawioną wyĪej konstrukcjĊ jako (__bridge void*)someObject, ale moĪe to nie byü to, o co Ci chodziáo. Tego typu rzutowaniom bardziej szczegóáowo przyjrzymy siĊ w podrozdziale „Wspóápraca z C”. Pule automatycznego zwalniania pamiõci 3 id returnObject(void) 4 { 5 return [[NSObject new] autorelease]; 6 } 7 8 int main(void) 9 { 10 @autorelease { 11 id object = returnObject(); 12 [object retain]; 13 } 14 // Tutaj obiekt traci waĪnoĞü. 15 [object release]; 16 return 0; 17 } Z pliku: autorelease.m Poza cyklami najwiĊkszym problemem w przypadku zliczania referencji są krótkie okresy, w których na obiekt nie wskazuje Īadna referencja. W jĊzyku C problemem jest decyzja, kto jest odpowiedzialny za alokowanie pamiĊci: wywoáujący czy wy- woáywany. W funkcjach takich jak sprintf() pamiĊü zajmuje wywoáujący. Niestety nie wie on, ile pamiĊci tak naprawdĊ jest potrzebne, wiĊc utworzono wariant o nazwie snprintf(), który informuje wywoáaną funkcjĊ o iloĞci dostĊpnej pamiĊci. Takie rozwiązanie wciąĪ moĪe sprawiaü problemy, wiĊc utworzono jeszcze jedną wersjĊ o nazwie asprintf(), która pozwala wywoáywanej funkcji zająü siĊ alokowaniem pamiĊci. JeĞli pamiĊü zajmuje wywoáywana funkcja, kto jest odpowiedzialny za jej zwol- nienie? Prawdopodobnie wywoáujący, ale poniewaĪ to nie on zająá pamiĊü, to programy sprawdzające równowagĊ miĊdzy wywoáaniami funkcji malloc() i free() nie poradzą sobie ze spostrzeĪeniem potencjalnego wycieku pamiĊci. 60 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ W Objective-C problem ten wystĊpuje jeszcze czĊĞciej. Wiele metod moĪe zwracaü obiekty tymczasowe, które muszą zostaü zwolnione. Z kolei gdy zwracają wskaĨnik na zmienną instancyjną, nie trzeba go zwalniaü. MoĪna by najpierw pozyskiwaü takie wskaĨniki, ale potem trzeba by pamiĊtaü, Īeby zwalniaü kaĪdy obiekt zwra- cany z metody. Szybko staáoby siĊ to mĊczące. Rozwiązaniem problemu jest pula automatycznego zwalniania pamiĊci. Po wy- sáaniu do obiektu wiadomoĞci –autorelease jest on dodawany do aktywnej w danym momencie puli NSAutoreleasePool. Gdy instancja puli jest niszczona, kaĪdemu dodanemu do niej obiektowi jest wysyáana wiadomoĞü –release. -autorelease to opóĨniona wiadomoĞü –release. Wysyáa siĊ ją do obiektu, gdy samemu nie potrzebuje siĊ juĪ referencji do niego, ale komuĞ innemu moĪe jeszcze byü potrzebna. JeĞli uĪywasz pĊtli wykonania NSRunLoop, pula automatycznego zwalniania pa- miĊci bĊdzie tworzona na początku, a niszczona na koĔcu kaĪdej iteracji pĊtli. Oznacza to, Īe Īaden tymczasowy obiekt nie zostanie zniszczony do koĔca obec- nej iteracji. JeĞli robisz coĞ, co wymaga duĪej iloĞci takich obiektów, moĪesz chcieü utworzyü nową pulĊ automatycznego zwalniania. Robi siĊ to w nastĊpujący sposób: id pool = [NSAutoreleasePool new]; [anObject doSomethingThatCreatesObjects]; [pool drain]; Zwróü uwagĊ, Īe aby zniszczyü pulĊ, trzeba jej wysáaü wiadomoĞü –drain, a nie –release. Jest tak, bo w trybie odĞmiecania pamiĊci Ğrodowisko uruchomieniowe Objective-C ignoruje wiadomoĞci –release. WiadomoĞü –drain jest wskazówką dla odĞmiecacza, ale w trybie odĞmiecania pamiĊci nie powoduje natychmiastowego zniszczenia puli. W OS X 10.7 firma Apple uczyniáa pulĊ automatycznego zwalniania pamiĊci czĊĞcią jĊzyka. Programy jawnie uĪywające NSAutoreleasePool są uwaĪane za niepoprawne w trybie ARC i zostaną odrzucone przez kompilator. Trzeba je za- stąpiü konstrukcją @autoreleasepool, definiującą region waĪnoĞci puli. W trybach innych niĪ ARC konstrukcja ta spowoduje wstawienie identycznego kodu jak w li- stingu powyĪej. W trybie ARC wstawione zostaną wywoáania funkcji objc_ autoreleasePoolPush() i objc_autoreleasePoolPop(), które wykonają podobną pracĊ. Konstruktory automatycznie zwalniajæce pamiúè 61 Konstruktory automatycznie zwalniajáce pamiõã 4 + (id)object 5 { 6 return [[[self alloc] init] autorelease]; 7 } Z pliku: namedConstructor.m W poprzednim podrozdziale powiedziaáem, Īe obiekty utworzone przy uĪyciu +alloc mają licznik referencji ustawiony na jeden. W rzeczywistoĞci wszystkie obiekty są tworzone z licznikiem ustawionym na jeden, ale obiekty tworzone przy uĪyciu na- zwanego konstruktora, np. +stringWithFormat: lub +array, są takĪe automatycznie usuwane z pamiĊci. By zachowaü obiekt tworzony przy uĪyciu jednego z tych mechanizmów, trzeba wysáaü mu wiadomoĞü –retain. W przeciwnym wypadku zostanie zniszczony w trakcie usuwania puli automatycznego zwalniania pamiĊci. Jest to konwencja, którą warto naĞladowaü we wáasnych klasach. JeĞli ktoĞ utworzy instancjĊ jednej z Twoich klas, korzystając z nazwanego konstruktora, bĊdzie oczekiwaá, Īe nie musi jej zwalniaü. Typowy nazwany konstruktor przypominaáby ten z początku tego podrozdziaáu. Zwróü uwagĊ, Īe poniewaĪ jest to metoda klasowa, obiekt self bĊdzie klasą. Wy- syáając wiadomoĞü +alloc do self zamiast do klasy o okreĞlonej nazwie, metoda moĪe dziaáaü poprawnie równieĪ w przypadku podklas. W trybie ARC te konwencje zostaáy sformalizowane w rodzinach metod. Metody, które zaczynają siĊ od sáów alloc, new, copy lub mutableCopy, zwracają referencjĊ wáasnoĞciową — referencjĊ, która musi zostaü zwolniona, jeĞli nie bĊdzie prze- chowywana. Inne metody zwracają referencje niewáasnoĞciowe, które muszą zostaü automatycznie zwolnione lub przechowane w miejscu, co do którego gwarantuje siĊ, Īe nie bĊdzie zwolnione. Automatyczne zwalnianie obiektów w akcesorach 34 - (NSString*)stringValue 35 { 36 return [[string retain] autorelease]; 37 } Z pliku: ivar.m 62 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ Innym powszechnym problemem ze zliczaniem referencji w formie zaimplemento- wanej przez Foundation jest czĊste niepozyskiwanie obiektów, które znajdują siĊ na stosie. RozwaĪmy nastĊpujący fragment kodu: NSString *oldString = [anObject stringValue]; [anObject setStringValue: newString]; JeĞli metoda –setStringValue: zostaáa zaimplementowana tak, jak sugerowaáem wczeĞniej, to wykonanie kodu skoĔczy siĊ przerwaniem aplikacji, bo obiekt, do którego odnosi siĊ oldString, zostanie usuniĊty przed ustawieniem nowej wartoĞci ciągu znakowego. Jest to problem mający dwa moĪliwe rozwiązania, obydwa ko- rzystające z puli automatycznego zwalniania pamiĊci. Pierwsze polega na auto- matycznym zwolnieniu starej wartoĞci podczas ustawiania nowej. Drugi to takie zdefiniowanie metody –stringValue, jak pokazano na początku tego podrozdziaáu. Zapewnia to, Īe ciąg znakowy nie zostanie przez przypadek zniszczony w trakcie normalnej pracy obiektu. Innym popularnym rozwiązaniem jest zastąpienie wia- domoĞci –copy wiadomoĞcią –retain. Jest to uĪyteczne, jeĞli zmienna instancyjna moĪe byü modyfikowana. JeĞli nie moĪna jej modyfikowaü, –copy bĊdzie odpo- wiednikiem –retain. JeĞli moĪna ją modyfikowaü, wywoáujący otrzyma obiekt, który nie bĊdzie ulegaá zmianom na skutek wysáanych mu wiadomoĞci. Wsparcie dla automatycznego odĴmiecania kolekcji 0 $ gcc -c -framework Cocoa -fobjc-gc-only collected.m 1 $ gcc -c -framework Cocoa -fobjc-gc collected.m Od wersji OS X 10.5 firma Apple wprowadziáa do Objective-C automatyczne od- Ğmiecanie kolekcji. Choü moĪe to upraszczaü Īycie programistom, w wiĊkszoĞci przypadków zmniejsza wydajnoĞü. OdĞmiecacz firmy Apple do Ğledzenia istnie- jących referencji zuĪywa duĪo pamiĊci i z tego powodu nie jest dostĊpny na iPhone’a. Nie jest teĪ obsáugiwany w starszych wersjach OS X, a jego obsáuga w GNUstep jest ograniczona. JeĞli chcesz pisaü przenoĞny kod, powinieneĞ unikaü odĞmiecania kolekcji. JeĞli skompilujesz kod w trybie odĞmiecania pamiĊci, wszystkie wiadomoĞci –retain, –release i –autorelease zostaną zignorowane. Kompilator automatycznie wstawi wywoáania odpowiednich funkcji przy kaĪdej operacji zapisu do pamiĊci na stercie. Wsparcie dla automatycznego odħmiecania kolekcji 63 ĩeby moĪna byáo uĪywaü odĞmiecania kolekcji, kod musi byü skompilowany w try- bie odĞmiecania pamiĊci. Przy kaĪdej operacji przypisania do pamiĊci na stercie wstawiane są wtedy wywoáania funkcji, które w Ğrodowisku uruchomieniowym systemu Mac są zadeklarowane w pliku objc-auto.h. Funkcje te upewniają siĊ, Īe odĞmiecacz kolekcji jest Ğwiadomy wykonanego przypisania. Są wymagane, bo odĞmiecacz dziaáa w tle, w osobnym wątku, usu- wając obiekty, do których nie moĪe znaleĨü referencji. OdĞmiecacz musi byü in- formowany o przestawianiu wskaĨników; mógáby przez przypadek usunąü obiekt, do którego przed momentem utworzyáeĞ referencjĊ. Podczas kompilacji z wáączonym odĞmiecaniem pamiĊci dostĊpne są dwie opcje. Po skompilowaniu z flagą –fobjc-gc-only kod bĊdzie wspieraá wyáącznie odĞmiecanie kolekcji. Po skompilowaniu z flagą –fobjc-gc kod bĊdzie obsáugiwaá zarówno zliczanie referencji, jak i automatyczne odĞmiecanie kolekcji. Jest to uĪyteczne, gdy kompilujesz framework. WciąĪ musisz pamiĊtaü, by w odpowiednich miejscach dodaü wywoáania –retain i –release, ale uĪytkownicy frameworku bĊdą mogli uĪywaü go z wáączonym lub wyáączonym odĞmiecaniem. 110 OBJC_EXPORT BOOL objc_atomicCompareAndSwapGlobal( id predicate, id replacement, volatile id * objectLocation) 111 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) OBJC_ARC_UNAVAILABLE; 112 OBJC_EXPORT BOOL objc_atomicCompareAndSwapGlobalBarrier(id predicate, id replacement, volatile id * objectLocation) 113 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) OBJC_ARC_UNAVAILABLE; 114 // automatyczna aktualizacja zmiennej instancyjnej 115 OBJC_EXPORT BOOL objc_atomicCompareAndSwapInstanceVariable(id predicate, id replacement, volatile id * objectLocation) 116 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) OBJC_ARC_UNAVAILABLE; 117 OBJC_EXPORT BOOL objc_atomicCompareAndSwapInstanceVariableBarrier (id predicate, id replacement, volatile id * objectLocation) 64 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ Wspóępraca z C W trybie odĞmiecania pamiĊci nie jest skanowana caáa pamiĊü. Dane zaalokowane przy uĪyciu malloc() są niewidoczne dla odĞmiecacza. JeĞli przekaĪesz do funk- cji z C wskaĨnik na obiekt w parametrze void*, a nastĊpnie funkcja przechowa go w pamiĊci zarezerwowanej malloc(), stanie siĊ niewidoczny dla odĞmiecacza i moĪe zostaü zwolniony, choü wciąĪ istnieją do niego referencje. W trybie ARC kompilator automatycznie zajmie siĊ wskaĨnikami na stosie i zmien- nymi instancyjnymi, ale nie bĊdzie Ğledziá wskaĨników w strukturach i wszystkich innych jawnie zadeklarowanych jako __unsafe_uretained. Normalnie przed wstawieniem obiektu na stertĊ wysáaábyĞ mu wiadomoĞü –retain. Nie dziaáa to jednak w trybie odĞmiecania pamiĊci i jest zabronione w trybie ARC. W zamian musisz uĪyü funkcji CFRetain(), inkrementującej licznik refe- rencji obiektu niezaleĪnie od obecnoĞci odĞmiecacza. OdĞmiecacz zwolni obiekt je- dynie wtedy, gdy licznik referencji osiągnie wartoĞü zero i nie bĊdzie moĪna zna- leĨü do niego Īadnej referencji w skanowanej pamiĊci. Gdy skoĔczysz pracĊ z referencją znajdującą siĊ poza obszarem Ğledzonym przez odĞmiecacz, bĊdziesz musiaá wywoáaü CFRelease(). ARC posiada bogatszy model pamiĊci do tego typu operacji. Jawne rzutowania obiektów na nieobiektowe wskaĨniki nie są juĪ dozwolone. Muszą byü zastąpione rzutowaniami mostkowanymi. RozwaĪmy nastĊpujący fragment kodu dziaáający w trybie innym niĪ ARC: void *aPointer = (void*)someObject; W trybie ARC rezultatem wykonania go byáoby utworzenie ze wskaĨnika Ğledzo- nego wskaĨnika nieĞledzonego. Nie jest to zamiana, którą chciaábyĞ wykonaü bez zastanowienia. Masz trzy podstawowe moĪliwoĞci. Pierwsza jest czĊsto wykorzy- stywana w przypadku zmiennych na stosie lub wskaĨników pokazujących na obiekty, co do których ma siĊ pewnoĞü, Īe wskazują na nie inne referencje: void *aPointer = (__bridge void*)someObject; PowyĪej wykonywane jest rzutowanie bez przekazania wáasnoĞci. JeĞli wszystkie pozostaáe referencje na someObject przestaną istnieü, aPointer zostanie wiszącym wskaĨnikiem. JeĞli wskaĨnik void* bĊdzie umieszczony na stosie z zamiarem przechowania wáa- snoĞciowej referencji do obiektu, powinieneĞ wykonaü rzutowanie mostkowane: void *aPointer = (__bridge_retained void*) someObject; Niszczenie obiektów 65 Spowoduje to wyjĊcie jednej referencji wáasnoĞciowej spod kontroli ARC. Jest to z grubsza odpowiednik wysáania do someObject wiadomoĞci –retain przed prze- chowaniem go we wskaĨniku. JeĞli napiszesz (__bridge_retained void*)someObject bez operacji przypisania, bĊdzie to informacja dla kompilatora, Īeby pozyskaá re- ferencjĊ na obiekt. Tego typu postĊpowanie uznawane jest za bardzo záy styl pro- gramowania. Podczas rzutowania z powrotem na wskaĨnik na obiekt powinieneĞ wykonaü odwrotną operacjĊ: id anotherObjectPointer = (__bridge_transfer id)aPointer; aPointer = NULL; Kod ten powoduje przekazanie wáasnoĞciowej referencji pod kontrolĊ ARC. ARC jest teraz odpowiedzialny za zwalnianie obiektu, wiĊc waĪne jest pamiĊtanie o wy- zerowaniu wskaĨnika z C. JeĞli nie przejmujesz wáasnoĞci nad wskaĨnikiem, po- winieneĞ uĪyü prostego rzutowania __bridge. Niszczenie obiektów 3 @interface Example : NSObject 4 { 5 void *cPointer; 6 id objectPointer; 7 } 8 @end 9 @implementation Example 10 - (void)finalize 11 { 12 if (NULL != cPointer) { free(cPointer); } 13 [super finalize]; 14 } 15 - (void)dealloc 16 { 17 if (NULL != cPointer) { free(cPointer); } 18 #if !__has_feature(objc_arc) 19 [objectPointer release]; 20 [super dealloc]; 21 #endif 22 } 23 @end Z pliku: dealloc.m Istnieją trzy metody wywoáywane podczas niszczenia obiektu zaleĪnie od wyko- rzystywanego trybu. Jedna jest uruchamiana za kaĪdym razem, ale nie moĪe byü napisana przez Ciebie. Metoda –.cxx_destruct jest zawsze wywoáywana przez 66 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ Ğrodowisko uruchomieniowe Objective-C i zajmuje siĊ niszczeniem pól, za któ- rych czyszczenie jest odpowiedzialny kompilator. Do kategorii tej naleĪą obiekty C++ w trybie Objective-C++ i wskaĨniki na obiekty Objective-C w trybie ARC. Dwie pozostaáe metody to –finalize i –dealloc. W trybie odĞmiecania pamiĊci nie musisz nic robiü, by usunąü referencje do obiektów Objective-C, ale wciąĪ musisz wykonaü czyszczenie zasobów, którymi nie zarządza odĞmiecacz pamiĊci. Do tej kategorii naleĪy zamykanie uchwytów do plików, zwalnianie pamiĊci za- alokowanej przy uĪyciu malloc() itd. JeĞli klasa ma zmienne instancyjne, które wymagają rĊcznego czyszczenia, powinieneĞ zadeklarowaü metodĊ –finalize. OdĈmiecacz pamiöci zwykle wywoäa metody –finalize w specjalnym wñtku. Oznacza to, Ĕe metody –finalize muszñ byè bezpieczne ze wzglödu na wñtki. JeĈli korzystajñ z globalnych zasobów, muszñ upew- niè siö, Ĕe nie spowoduje to problemów. JeĞli nie uĪywasz odĞmiecania pamiĊci, sprzątanie powinieneĞ wykonaü w metodzie –dealloc. ZawartoĞü metody zaleĪy od tego, czy uĪywasz ARC. Dawniej metody – dealloc byáy wypeánione wiadomoĞciami –release wysyáanymi do kaĪdej zmiennej instancyjnej, którą deklarowaáa klasa. JeĞli korzystasz z ARC, nie jest to wymagane. ARC zwolni wszystkie wáasnoĞciowe referencje do obiektów w –.cxx_destruct, wiĊc w –dealloc bĊdziesz musiaá sprzątnąü jedynie zmienne in- stancyjne niebĊdące obiektami. Zarówno w trybie odĞmiecania pamiĊci, jak i rĊcznego pozyskiwania i zwalniania re- ferencji powinieneĞ przekazaü wiadomoĞü do nadklasy, wywoáując [super dealloc] lub [super finalize]. W trybie ARC jawne wywoáanie –dealloc jest niedozwolone. Zamiast tego ARC sam wstawi wywoáanie [super dealloc] na koĔcu metody –dealloc w kaĪdej klasie niebĊdącej korzeniem. Zwróü uwagĊ, Īe kod na początku tego podrozdziaáu jest nadmiernie skompliko- wany. W prawdziwym kodzie maáo prawdopodobne jest, ĪebyĞ musiaá wspieraü zarówno tryb ARC, jak i tryb rĊcznego pozyskiwania i zwalniania referencji. Tryby te mogą wspóáistnieü w jednym programie, ale jedynym rozsądnym powo- dem wspierania jakiegokolwiek trybu poza ARC jest chĊü zachowania zgodnoĞci ze starymi kompilatorami. Sęabe referencje 4 __weak id weak; 5 6 int main(void) 7 { Sđabe referencje 67 8 id obj = [NSObject new]; 9 weak = obj; 10 obj = nil; 11 objc_collect(OBJC_FULL_COLLECTION); 12 fprintf(stderr, Sïaba referencja: p\n , weak); 13 return 0; 14 } Jednym z najprzyjemniejszych elementów implementacji odĞmiecania pamiĊci firmy Apple jest istnienie zerujących siĊ, sáabych referencji. Niepozyskane wskaĨniki są w starej dokumentacji Objective-C czĊsto okreĞlane mianem „sáabych”. WskaĨniki te mogą przetrwaü dáuĪej niĪ obiekt, na który wskazują. Niestety nie ma automa- tycznego sposobu sprawdzania, czy są wciąĪ poprawne. Sáabe referencje okazaáy siĊ tak przydatne podczas odĞmiecania pamiĊci, Īe są teraz wspierane takĪe przez ARC, choü mają odrobinĊ inne znaczenie. Implementacje ARC zachowujące wsteczną kompatybilnoĞü nie obsáugują sáabych referencji, wiĊc wsparcie firmy Apple jest obecnie jedynie na platformach OS X 10.7 i iOS 5 lub póĨniejszych. Säabe referencje w Ĉrodowisku zliczania referencji sñ czösto uĔywane do eliminowania cykli. Nie jest to konieczne w Ĉrodowisku, w którym referencje sñ Ĉledzone. W tym przypadku w miejscach potencjalnego tworzenia cykli oraz w trakcie tworzenia delegat moĔesz uĔywaè sil- nych referencji. JeĞli zadeklarujesz wskaĨnik na obiekt ze sáowem __weak, utworzysz zerującą siĊ, sáabą referencjĊ. OdĞmiecacz pamiĊci nie weĨmie jej pod uwagĊ podczas ustalania, czy obiekt wciąĪ istnieje, a w trybie ARC po przypisaniu do niej nie zostanie zwiĊk- szony licznik referencji. JeĞli wszystkie referencje do obiektu są sáabe, moĪe on byü zniszczony. Po tej operacji wszystkie sáabe referencje bĊdą zwracaáy nil. Sáabe referencje są zwykle uĪywane w poáączeniu z konstrukcjami takimi jak powiadomienia. Sáabą referencjĊ do obiektu moĪna przechowywaü i wysyáaü mu wiadomoĞci tak dáugo, jak dáugo ktoĞ inny posiada do niego referencjĊ. Gdy refe- rencja przestanie istnieü, obiekt moĪna automatycznie usunąü z mechanizmu po- wiadamiania. Cocoa posiada teraz kolekcje pozwalające na przechowywanie sáabych referencji. Starsze wersje frameworku Foundation zawieraáy typy utworzone w jĊzyku C: NSMapTable oraz NSHashTable wraz z zestawem funkcji C, które moĪna z nimi wyko- rzystaü. Interfejsy te są wciąĪ dostĊpne, ale w wersji 10.5 Apple zamieniáo te typy na klasy. 68 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ Typ NSMapTable jest ogólniejszą formą NSDictionary. MoĪna w nim przechowy- waü dowolne typy o rozmiarze wskaĨnika zarówno w kluczach, jak i wartoĞciach. W trybie odĞmiecania pamiĊci moĪesz wykorzystywaü tĊ klasĊ do przecho- wywania mapowaĔ z i do silnych lub sáabych wskaĨników. Jest to przydatne np. w NSNotificationCenter, w którym przechowuje siĊ obiekty mogące otrzymywaü powiadomienia. Gdy obiekty te przestaną istnieü, są automatycznie usuwane z ko- lekcji, a powiadomienia nie są juĪ wiĊcej wysyáane. Przykáad na początku podrozdziaáu pokazuje waĪną róĪnicĊ miĊdzy trybami ARC i odĞmiecania pamiĊci. JeĞli skompilujesz i uruchomisz go z wáączonym odĞmie- caniem pamiĊci, wypisany zostanie przypuszczalnie adres obiektu. Jest tak, gdyĪ odĞmiecacz pamiĊci podczas skanowania stosu wciąĪ widzi stare wartoĞci tym- czasowe. W odróĪnieniu od odĞmiecacza pamiĊci w trybie ARC zawsze zostanie wypisana wartoĞü 0. ARC jest zupeánie deterministyczny. Przypisanie nil do silnego wskaĨnika dekrementuje licznik referencji obiektu i powoduje dealokacjĊ. Sáaby wskaĨnik jest zerowany, nim zacznie siĊ dealokacja, wiĊc gwarantowane jest, Īe przyjmie wartoĞü zero, nim wywoáana zostanie funkcja fprintf(). Alokowanie skanowanej pamiõci 15 id *buffer = 16 NSAllocateCollectable( 17 10 * sizeof(id), 18 NSScannedOption); Z pliku: gc.m PamiĊü zajĊta przy uĪyciu funkcji malloc() jest niewidoczna dla odĞmiecacza pamiĊci. MoĪe to byü problemem, np. jeĞli potrzebujesz tablicy C zawierającej obiekty. WidzieliĞmy juĪ rozwiązanie tego problemu. MoĪesz wywoáaü CFRetain() dla obiektu, który masz zamiar przechowaü w tablicy, oraz CFRelease() dla znaj- dującej siĊ w niej starej wartoĞci, a nastĊpnie je zamieniü. Nie jest to idealne rozwiązanie, ale dziaáa. Inną opcją jest alokacja fragmentu pa- miĊci tak, by byá widoczny dla odĞmiecacza. Funkcja NSAllocateCollectable() jest podobna do malloc() z dwoma istotnymi róĪnicami. Po pierwsze: zwracana przez nią pamiĊü bĊdzie odĞmiecana. Nie istnieje jej odpo- wiednik w postaci funkcji NSFreeCollectable(). Gdy ostatni wskaĨnik na bufor zniknie, bufor zostanie usuniĊty. Alokowanie skanowanej pamiúci 69 OdĈmiecacz firmy Apple nie wspiera wskaĒników do wnötrza bufora, wiöc musisz upewniè siö, Ĕe utrzymujesz wskaĒnik na poczñtek re- gionu. Inne wskaĒniki nie powstrzymajñ procesu usuniöcia go. Drugą róĪnicą jest istnienie w tej funkcji drugiego parametru, definiującego po- Īądany typ pamiĊci. JeĞli chcesz uĪywaü bufora do przechowywania typów C, moĪesz wstawiü tu zero. JeĞli przekaĪesz NSScannedOption, zwrócony bufor bĊdzie przeszukiwany jako moĪliwe Ĩródáo wskaĨników na obiekty oraz wskaĨników na inne obszary pamiĊci zwracane przez NSAllocateCollectable(). 70 Rozdziađ 3 ‹ Zarzædzanie pamiúciæ Skorowidz A abstrakcyjna nadklasa, 82 adres URL, 213 aktywna pĊtla wykonania, 211 algebraiczny system typów, 17 aplikacje Cocoa, 146 ARC, 54, 57 archwizowanie obiektów, 74 arytmetyka staáopozycyjna, 89 ASCII, 98 atrybuty pliku, 170 automatyczne obudowywanie, auto-boxing, 150 odĞmiecanie kolekcji, 62 zliczanie referencji, 53 zwalnianie pamiĊci, 60 B Berkley Sockets API, 205 bezkosztowa obsáuga wyjątków, 156 biblioteka GNUstep Base, 25 libdispatch, 195 libobjc, 18 blok @finally, 161 @try, 161 bloki, 49, 116 báąd w kodzie, 164 báĊdy, 155 C Chisnall David, 9 ciąg formatujący, 103 ciąg znakowy dzielenie, 101 kodowanie, 98 kopiowanie, 101 porównywanie, 94 przetwarzanie, 96 przycinanie, 100 tworzenie, 94, 103 wzorce, 105 Clang, 22, 23 cykl, 57 D data, 125 data odniesienia, 124 debuger GNU, 215 LLVM, 216 deklarowanie klas, 31 typów, 26 delegowanie, 79 DNS-SD, 207 dodawanie metod, 36 dodawanie zmiennych, 232 domena, 164 Local, lokalne, 176 Network, sieü, 176 System, 176 User, uĪytkownik, 176 domeny systemu plików, 175 ustawieĔ, 136 domkniĊcie, 189 dostĊp do wartoĞci, 147 dwufazowe tworzenie obiektów, 71 dyrektywa @encode(), 48 @implementation, 37 @selector(), 31 @synthesize, 42 dziedziczenie z kolekcji, 118 dzielenie ciągów znakowych, 101 E enumerator, 115 Erlang, 155 F firma NeXT, 25 format JSON, 134 OpenStep, 133 framework Application Kit, 19 Cocoa, 18 Foundation Kit, 19, 51 236 Skorowidz funkcja 60 _ autoreleasePoolPush(), _Block_copy(), 50, 193 _Block_release(), 193 _start, 142 alarm(), 128 asprintf(), 59, 103 CFRetain(), 64 class_conforms ´ToProtocol(), 229 dispatch_get_global_ ´queue(), 196 ETGetOptionsDictionary(), 143 exit(), 145 fprintf(), 68 free(), 59 getaddrinfo(), 207 getCounter(), 49, 50 getopt(), 143 gettimeofday(), 126 longjmp(), 156 main(), 47 malloc(), 59 memcpy(), 73 NSAllocateCollectable(), NSClassFromString(), 230 NSLog(), 104, 221 objc_autorelease ´PoolPop(), 60 objc_exception_throw(), 68 219 objc_msg_lookup(), 217 objc_msgSend(), 217, 224 objc_release(), 53 objc_retain(), 53 object_getClass(), 45 object_getIndexedIvars(), 232 object_setClass(), 45 printf(), 91, 103 qsort(), 31 scanf(), 91 sprintf(), 59, 91 sscanf(), 91 strsep(), 101 strtok(), 101 strtok_r(), 101 time(), 124 writeBack(), 55 funkcje anonimowe, 49, 189 konwertujące, 99 G GCC, 46 GNUstep runtime, 22 H hierarchia NSControl, 80 I inicjalizacja statyczna, 46 inspekcja obiektów, 215 Instance Method Pointer, 28 instancja NSDecimalNumber, 89 NSFont, 107 singletonu, 82 interfejs kqueue(), 206 ivar, 33 ivars, 26, 52, 232 J jednostka zarządzania pamiĊcią, 168 jĊzyk Smalltalk, 17 StrongTalk, 17 JSON, JavaScript Object Notation, 134 K kalendarz, 125 kanoniczne ustawienia regionalne, 91, 96 kategorie, 36, 139 klasa LKMessageSend, 77 NSApplication, 128 NSArray, 110 NSAssertionHandler, 220 NSAttributedString, 106, 107 NSCalendar, 125 NSDate, 124, 125 NSDateFormatter, 126 NSDecimal, 89 NSDictionary, 148 NSDistantObject, 209 NSError, 164 NSException, 159, 219 NSFileHandle, 206, 207 NSFileManager, 169, 170 NSIndexSet, 111 NSMutableArray, 111 NSNotificationQueue, 201 NSProcessInfo, 141 NSPropertyList ´Serialization, 132 NSRecursiveLock, 182 NSRegularExpression, 105 NSRunLoop, 128 NSScanner, 92, 127 NSSet, 112, 117 NSThread, 180 NSTimer, 84, 128 NSURLConnection, 213 NSURLRequest, 213 NSUserDefaults, 136, 137 NSView, 80 Pair, 82 TypedArray, 119 UIApplication, 128 klastry klas, 82, 86, 96 klasy inspekcja, 229 odszukiwanie, 228 odszukiwanie wedáug nazwy, 224 tworzenie, 231 kodowanie klucz-wartoĞü, 114, 147 tekstu, 99 typów, 47 typu, 48 typu Objective-C, 86 UTF-8, 93 kolejka FIFO, 196 kolekcje, 109 kompilator GCC, 23 kompilowanie programów, 23 Skorowidz 237 konstrukcja @autoreleasepool, 60 konwersja ciągu znakowego, kopiowanie obiektów, 72 KVC, key-value coding, 147, 90 151 KVO, key-value observing, 147, 152 kwalifikator __block, 191 static, 192 L library, biblioteka, 176 liczba argumentów, 103 liczba binarna, 89 licznik referencji, 102 licznik referencji obiektu, 52 linia komend, 143 Lisp, 155 lista z przeskokami, skip list, 110 listy wáaĞciwoĞci, 103, 129, 203 Ę áapanie wyjątków, 157 áączenie siĊ z serwerami, 207 M makro assert(), 220 CFSTR(), 94 NS_BLOCK_ASSERTS, 221 NSAssert(), 220 NSCAssert(), 220 mapa, 113 mechanizm powiadomieĔ, 199 mechanizm wiązania, 152 metaklasy, 231 metoda +alloc, 72 +allocWithZone, 79 +bundleForClass, 175 +initialize, 47 +pathWithComponents, 172 +stringWithFormat, 90 –addToQueue, 186 –compare, 96 -countForObject, 113 –dealloc, 58 –description, 103 –descriptionWithLocale, 90 –fileExistsAtPath:is ´Directory, 173 –finalize, 66 –forward, 227 –hash, 112 –init, 72 –initWithCoder, 76 –initWithString, 139 –isEqualToString, 95 KVC, 148 –lastIndex, 111 –makeObjects ´PerformSelector, 116 malloc(), 51 –member, 117 –newCopyStarted, 204 –objectForKey, 136, 148 –pathComponents, 172 –pathForResource:of ´Type, 174 –readUTF8String, 207 –setDateFormat, 127 –setStringValue, 62 –setValue:forKey, 148 sprintf(), 90 –start, 128 –stringValue, 139 –valueForKey, 148 –writeUTF8String, 207 metody o zmiennej liczbie argumentów, 110 wirtualne, 120 migracja, 58 MMU, memory management unit, 168 model obiektowy, 15 multicast DNS, 211 N nadklasa NSObject, 33 NSProxy, 33 nagáe zakoĔczenie programu, 145 narzĊdzie do migracji, 58 gnustep-config, 24 pbxbuild, 24 plutil, 134 NeXT, 20 niszczenie obiektów, 65 notacja kropkowa, 39, 151 O obiekt naprawiający, 165 NSAutoreleasePool, 104 NSCharacterSet, 92, 100 NSColor, 138 NSLocale, 144 self, 61 obiekty ciągów znakowych, 93 obserwacja klucz-wartoĞü, 147 obsáuga bloków, 189 obsáuga wyjątków, 157 odczytywanie pliku, 167 odĞmiecanie kolekcji, 63 opakowywanie, boxing, 86 opcja copy, 41 opcja –framework, 24 OpenStep, 98 OS X GCC, 23 P pakiety, bundles, 174 pĊtla wykonania, 84, 128 pĊtla wykonania NSRunLoop, 60 platforma POWER6, 89 plik example.plist, 130 pliki implementacji, 32 pliki nagáówkowe, 32 POD, plain old data type, 122 238 Skorowidz podklasa NSEnumerator, 115 NSNumber, 90 NSObject, 38 NSSet, 113 NSString, 83 podmiana wskaĨnika isa, 154, 232 POSIX, 142, 179 powiadomienia kolejkowanie, 201 przesyáanie, 202 wysyáanie, 201 Īądanie, 199 priorytet pliku, 175 priorytet wątku, 180 proces przestrzeni pracy, 167 programowanie sterowane zdarzeniami, 84 projekt GNU, 20 protokoáy nieformalne, 226 protokóá Collection, 37 ETCollection, 37 NSCoding, 76, 139 NSCopying, 50, 73 NSLocking, 185 NSObject, 35, 116 TCP/IP, 205 przechowywanie kolekcji, 130 obiektów, 120, 138 ustawieĔ, 135 przedwczesna optymalizacja, 95 przejrzysta wersja, 135 przesyáanie obiektów, 208 pseudozmienna super, 43 punkt zatrzymania, breakpoint, 218 QTKit, 123 Q R referencje niewáasnoĞciowe, 52 referencje wáasnoĞciowe, 52, 61 Rhapsody DR2, 175 rozmiar wskaĨnika, 86 rozszerzenie .h, 32 rozszerzenie .m, 32 rozszerzenie klasy, 37 rzucanie obiektów, 158 rzutowanie mostkowane, 64 mostkowane __bridge, 58 wskaĨników, 16 S scheduler, 181 SEH, structured exception handling, 156 selektory, 30 selektory typowane, 31 Simula, 16 singletony, 78 skojarzone referencje, 233 skrót obiektu, 112 sáabe referencje, 67 sáownik, 113 NSDictionary, 159 wątku, 184 sáowo kluczowe, 158 @defs, 44 @end, 32 @implementation, 32 @interface, 32, 33 @private, 33 @protocol(), 35 @public, 33 @synthesize, 42 __block, 49 __thread, 184 __unsafe_unretained, 57 __weak, 57 _cmd, 42 const, 27 nonatomic, 40 self, 42 sáownik, 184 struct, 26 super, 43 this, 42 throw, 160 Smalltalk, 25, 155 stoper, 128 StrongTalk, 17 struktura NSRange, 18 strukturalna obsáuga wyjątków, 156 system OPENSTEP, 146 OS X, 22, 24 OS X 10.7, 23 Solaris, 19 Symbian, 22 systemy plików, 173 szybkie enumerowanie, 97, 115 ij ĞcieĪki do klucza, 151 Ğrodowisko uruchomieniowe GNU, 224 GNUstep, 22 T tablica asocjacyjna, 113 tablice, 111 test Ingallsa, 18 TLB, 195 tryb ILP32, 85 LP64, 85 tworzenie typ klas, 231 sáownika, 113 wątków, 179 wáasnych kolejek, 196 Class, 27 IMP, 28 long, 86 NSDecimal, 89 NSMapTable, 68 NSString*, 34 NSTimeInterval, 123 readwrite, 40 SEL, 27, 31 unichar, 93 typy podstawowe, 85 wbudowane, 85 zmiennoprzecinkowe, 85 Skorowidz 239 U URL, Uniform Resource Locator, 212 W wartoĞü nil, 29, 225 wątki rywalizacja, 181 synchronizacja, 182 wczytywanie danych, 213 wĊzáy równolegáe, 210 wiadomoĞci przekierowywanie, 227 wysyáanie, 223 wiadomoĞü +alloc, 61, 72, 82 +defaultCenter, 200 +new, 71 –autorelease, 58, 84 –characterIsMember, 100 –compare, 31 –copy, 102 –copyWithZone, 73 –countForObject, 113 –dealloc, 51 –decimalNumberBy ´Adding, 89 –decimalValue, 89 –description, 103 –drain, 60 –forwardInvocation, 209 –integerValue, 90 –isEqual, 95, 112 –isProxy, 45 –readDataOfLength, 169 –release, 58, 60 –retain, 58 –retainCount, 52 –stringForKey, 136 –stringValue, 95 –threadDictionary, 184 –timeIntervalSinceDate, 126 –UTF8String, 97 –waitForDataInBackground ´AndNotify, 206 wiązania Cocoa, 151 worek, bag, 113 wskaĨnik, pointer, 86 isa, 44, 45, 50 na metody instancyjne, 28 na NSError*, 169 na strukturĊ, 43 void*, 64 wskaĨniki na obiekty, 26 wyjątki, 155 NSInternalConsistency ´Exception, 220 z nawracaniem, resumable
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Objective-C. Leksykon profesjonalisty
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: