Popatrzmy na kilka prostych przykładów. Podstawowa składnia wywoływania metod obiektu wygląda jak poniżej:
[object method];
[object methodWithInput:input];
Metody mogą zwracać wartość:
output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];
Można również wywoływać metody bezpośrednio na klasach. Właśnie w ten sposób tworzy się obiekty. W poniższym przykładzie wywołujemy metodę string
na klasie NSString
. Zwraca ona nowy obiekt klasy NSString
:
id myObject = [NSString string];
Typ id oznacza, że zmienna myObject
może odnosić się do obiektu dowolnego typu. W takim układzie tak właściwa klasa, jak metody, które implementuje, nie są znane podczas kompilacji aplikacji.
W tym przykładzie doskonale wiemy, że obiekt będzie typu NSString, więc możemy określić w kodzie jego typ:
NSString* myString = [NSString string];
Odtąd jest to zmienna klasy NSString
, więc kompilator ostrzeże nas jeśli będziemy próbować używania na niej metod, których klasa NSString
nie obsługuje.
Warto zwrócić szczególną uwagę na symbol wskaźnika, który znasz doskonale z C. Wszystkie obiekty w Objective-C muszą być adresowane wskaźnikami. Typ id
jest predefiniowany jako typ wskaźnikowy, więc w nim jednym gwiazdki nie potrzeba. Ale to wyjątek.
W wielu językach zagnieżdżone metody lub funkcjie wyglądają jak poniżej:
function1 ( function2() );
Wynik function2
jest przekazywany jako argument do function1
. W Objective-C zagnieżdżenia wyglądają tak:
[NSString stringWithFormat:[prefs format]];
Aby uniknąć myśli samobójczych przy próbie zrozumienia własnego kodu, warto unikać zagnieżdżania głębszego niż dwa poziomy w jednej linii.
Niektóre metody przyjmują wiele wartości wejściowych. W Objective-C, nazwa metody może być rozbita na kilka części. Prototyp takiej metody wygląda jak poniżej:
- (BOOL) writeToFile:(NSString *) path
atomically:(BOOL) useAuxiliaryFile;
Nie należy przejmować się enterami. Rozdzielenie wieloargumentowej metody na kilka linii skutecznie poprawia jej czytelność a w żaden sposób nie ma wpływu na jej działanie. Wyrównywanie tak podzielonej metody do linii dwukropków to standard przemysłowy który automatycznie realizuje za programistę Xcode.
Podobną metodę wywołuje się w poniższy sposób:
BOOL result = [myData writeToFile:@"/tmp/log.txt"
atomically:NO];
Nie są to tylko nazwy argumentów. Dla całego programu właściwą nazwą tej metody jest writeToFile:atomically:
.
Zmienne instancji są domyślnie prywatne w Objective-C. Stąd aby ustawić lub pobrać ich wartość należy używać akcesorów. Istnieją dla nich dwie możliwe składnie. Tradycyjna (dla Objective-C 1.x i wyższych):
[photo setCaption:@"Day at the Beach"];
output = [photo caption];
Kod w drugiej linii nie odczytuje zmiennej instancji bezpośrednio, a wywołuje na obiekcie metodę caption
. Inaczej niż w C++ czy w Javie nie poprzedzamy tej metody prefiksem get
. To zupełnie bezsensowne, skoro i tak domyślną akcją jest pobranie jakiejś wartości.
Gdziekolwiek używamy kodu wewnątrz nawiasów kwadratowych, wysyłamy wiadomość do klasy albo jej obiektu.
Kropkowa składnia dla setterów i getterów została wprowadzona w 2006 roku w Objective-C 2.0:
photo.caption = @"Day at the Beach";
output = photo.caption;
Można używać dowolnej ze składni akcesorów ale należy stosować ją konsekwentnie w obrębie jednego projektu. Poza tym, należy pamiętać aby używać składni kropkowej tylko dla setterów i getterów. Nigdy dla innych metod.
Istnieją dwa podstawowe sposoby na tworzenie obiektów. Pierwszy był już użyty punkcie pierwszym:
NSString* myString = [NSString string];
To o wiele wygodniejszy, prostszy sposób, sprawdzający się w wielu sytuacjach. W wielu innych, niestety, należy stworzyć obiekt w bardziej manualny sposób:
NSString* myString = [[NSString alloc] init];
Używamy tu zagnieżdżonego wywołania metody. Pierwszą metodą jest alloc
, wywołany bezpośrednio na klasie NSString
. To niskopoziomowa metoda alokująca pamięć i tworząca instancję obiektu. Druga, init
inicjalizuje wszystkie potrzebne obiektowi, prywatne zmienne.
Tak naprawdę to nigdy nie wiadomo, co robi init
. Wszystkie akcje wewnątrz niego są ukryte wewnątrz implementacji klasy. Ale skoro i tak jesteśmy tylko jej użytkownikiem, można spokojnie przestać się tym przejmować.
W niektórych przypadkach konieczne jest użycie innej wersji metody init
, która przyjmuje argumenty:
NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];
Logowanie, jako prowadzenie logów. Albo inaczej dzienników. W sensie wyświetlania w konsoli informacji zwrotnej z programu w formie sformatowanego odpowiednie tekstu.
Logowanie wiadomości do konsoli w Objective-C jest bardzo proste. W zasadzie, służąca do tego funkcja NSLog()
jest prawie identyczna jak znana z C funkcja printf()
. Jedyną różnicą jest dodatkowy łańcuch formatujący dla obiektów (%@
).
NSLog ( @"The current date and time is: %@", [NSDate date] );
Bez trudu można logować do konsoli obiekt. Funkcja NSLog()
wywołuje wtedy na nim metodę description i wyświetla zwracany przez niego łańcuch (NSString
). Możesz przeciążyć metodę description w swojej klasie, aby dostosować logowany w takim przypadku łańcuch.