ACROd tego miesiąca stałem się programistą  Objective-C. Chociaż ten termin nie powinien sobie jeszcze przypisywać biorąc pod uwagę ,że obecnie uczę się składni języka oglądając programy Hello World. W najbliższym czasie na blogu będzie dużo wpisów o Objective-C. Tak czy siak miałem oczywiście interesują konwersację z swoim współlokatorem oraz najlepszy przyjacielem na temat moich zdolności programistycznych.

Jeśli czytałeś ten wpis to wiesz ,że od czasu do czasu próbujemy sobie udowodnić kto z nas jest lepszy opowiadając sobie o tym co robimy w pracy. Biorąc pod uwagę ,że on pracuje w banku nie jest to łatwe zadanie.

Punkt rozmowy polegał na tym ,że ponieważ ja nie programowałem wcześniej w językach w których trzeba zarządzać pamięcią własnoręcznie ( C , C++ ) to nauką języka Objective-C będzie ciężka.

No cóż z miło chęcią mogę powiedzieć ,że mój kolega się myli.  Przynajmniej częściowo.

Otóż kompilator Objective-C oferuje mechanizm “Automatic Reference Counting” (ARC).

Mechanizm ten w dużym stopniu przekłada brzmienie i odpowiedzialność w zarządzaniu pamięci od programisty do automatu.   ARC także usuwa potencjalne bugi, które mógłby się pojawić w wyniku wycieku pamięci.

Nie jest to mechanizm Garbage Collection pod inną nazwą.  Po prostu proces dodania linijki kodu, która by oznaczyła  obiektu do zwolnienia z pamięci został zautomatyzowany.

Gdy ARC jest włączone spokojnie możesz napisać taki kod bez żadnych obaw.

NSObject *obj = [[NSObject alloc] init];
// do some stuff

ARC automatycznie doda następującą linijkę kodu.

NSObject *obj = [[NSObject alloc] init];
// do some stuff
[obj release]; // **Added by ARC**

Oto diagram z dokumentacji Apple, który implikuje, że bez linijek zwalniających pamięć  pianie kodu jest dużo szybsze.

Jest to na pewno prawda zwłaszcza jeśli jesteś początkującym programistom Objective-C.

ACR Szybsze pisanie kodu

Gdy ARC jest włączone nie można nawet napisać swojego kodu zwalniającego pamięć.

Release not

Zasady działania ARC

Jestem początkującym programistą wiec szczerze mówiąc nie powinno mnie interesować jak programowanie wyglądało “przed” ,ale nie powiem mechanizm ARC wydawał mi się podejrzany. Musiałem więc sprawdzić dokładnie jak on działa. Z resztą przez mechanizm ARC programy z niektórych poradników odmawiają posłuszeństwa.

Oto co dzieje z kodem gdy ARC jest włączone.

  • Alloc i Init Obiektów
    • Tworzenie obiektów działa tak samo ,ale nie można wywołać  następujących funkcji  (anyretain /release/autorelease/retainCount). Użycie selektorów niebezpośrednio też jest zakazane.
  • Metody Dealloc
    • Generalnie te metody zostaną utworzone za ciebie. Nie powinieneś wywoływać metod dealloc bezpośrednio. Możesz jednak utworzyć swoją metodę dealloc, która by zwalniała zasoby inne niż instancję zmiennych. Gdy więc wywołasz swojego dealloc nie używaj wywołania wyżej [super dealloc]. To zostanie zrobione za ciebie.
  • Deklarowanie właściwości
    • Przed ARC programista musiał powiedzieć kompilatorowi jak pamięć powinna być zarządzania używając specjalnych dyrektyw (theassign, retain, copy). Te parametry nie są używane w ARC. Zamiast tego mamy silne i słabe parametry, które mówią kompilatorowi jak powinien traktować te właściwości.
  • Wskaźniki do struktur C
    • Dokumentacja silnie wskazuje na używanie klas zamiast struktur. Ma to sens ponieważ ACR struktur by nie obsłużył. Jeśli migrujesz swój kod do wersji ACR prawdopodobnie dostaniesz małego bólu głowy z tego powodu.
      • ARC jednak może być wybiorczo wyłączone dla pojedynczego pliku,
  • Rzutowanie pomiędzy id i void
    • Woo dosyć zawansowany tematy. Rzutowanie te odbywa się gdy obiekty z biblioteki C gadają z bibliotekami Objective-C. Jest to znane pod nazwą Toll Free Bridging.
      • Mając włączony ARC musisz dać kompilatorowi pewne wskazów kiedy obiekty z biblioteki Core Foundation języka C znajdują się poza kontrolą ARC i sam je obsłużyć.
      • Osobiście nie mam pojęcia o czym teraz piszę xD ,ale dużo można dowiedzieć się z Internetu.
  • Przy użyciu ARC pojawia się nowa dyrektywa “@autorelasepool”, która zastępuję NSAutoReleasePool.NSAutoReleasePool.
    • Co oznacza ,że kod  aplikacji konsolowej “hello world” teraz wygląda tak.
      • image
  • Inna ciekawostka. Klasy operujące na pamięci  “Zone based” nie istnieją już w SDK. Nie możesz więc użyć obiektów NSAllocateObject i NSDeallocateObject

Deklarowanie właściwości z ARC

Okej więc jak deklarujemy właściwości w nowoczesny programowaniu Objective-C.

Oto jak wygląda podział na silną i słabą referencję.

Silna referencja

Silna referencja jest to referencja (duh) do obiektu, który zatrzymuje się przed operacją zwalniania (deallocated) z powodu swojego właściciela. Mówiąc proście ma on związek ze swoim właścicielem . Wcześniej kod by wyglądał tak.

// Non-ARC Compliant Declaration
@property(retain) NSObject *obj;

ARC zrobi mniej więcej to samo gdy użyjemy poniższej składni.

// ARC Compliant Declaration
@property(strong) NSObject *obj;

Wtedy ARC zadba oto aby instancja ten klasy dzieliła swoje życie z referowanym obiektem. (Nie będzie mogła być zwolniona (deallocated) przed swoim właścicielem).

Słabe referencje

Słabe referencje działają odwrotnie. Jeśli obiekt dziecko nie dzielić odpowiedzialności z obiektem rodzica wtedy powinniśmy użyć słabej referencji.

// ARC Compliant Declaration
@property(weak) NSObject *parentObj;

Kwalifikatory dla regularnych zmiennych

Dla regularnych zmiennych mamy następujące dyrektywy.

__strong
__weak
__unsafe_unretained
__autoreleasing

Te dyrektywy nie są często używane. Możesz się jednak z nimi spotkać w trakcie migracji kodu. Generalnie korzystamy z dyrektyw “weak” i “strong”.

  • ___strong:  jest to domyślny zapis i nie musi być on deklarowany. To oznacza ,że życie utworzonego obiektu jest zależne od obecnego zakresu kodu.
    • Obecny zakres kodu” referuje się do nawiasów klamrowych w których opisujemy działanie metod, pętl bloków if i itp.
  • ___weak: oznacza ,że obiekt może być zniszczony w każdym momencie. Jest to użyteczne tylko wtedy gdy obiekt ma już silną referencje gdzieś indziej. Gdy zmienna zostanie zniszczona jest ona ustawiona na nil (czyli null).
  • ___unsafe_unretained : działa podobnie jak ___weak ,ale jego wskaźnik nie jest ustawiony na nil gdy obiekt jest zwolniony (deallocated).
  • ___autoreleasing: Jest on używany gdy chcemy przesłać obiekt jako referencje. Przykładem jest obiekt NSError.

ARC jest super

ACR na pewno jest wspaniałą rzeczą gdyż jako oficjalny programista WEBOWY nie mam dużego pojęcia na temat zarządzania pamięci w językach nisko poziomowych.

Z drugie strony miałem pewną obawę i musiałem się upewnić jak ARC dokładnie działa.

Książka Objective-C

Był to dobry pomysł ponieważ teraz wie ,że większość poradników  jak i  książka, którą kupiłem do nauki Objective-C posiadają nieaktualne informację.

Programy hello world opisane krok po kroku nie działają ,że względu na ARC.

image

Dla zawansowane programisty Objective-C zapewne w głowie rodzi się pytanie czy samodzielne zarządzanie działa lepiej niż automatyczne. Niestety ,ale  zwycięstwo stoi po stronie automatu. Jednak jak każdy automat nie działa on w bardzo zawansowany przypadkach np. Toll Free Bridging. .