2012-04-26 14 views
45

Czy istnieje różnica między używaniem podkreślenia i użyciem słowa kluczowego self w Objective-C podczas wywoływania @property?Różnica między _ i self. w Objective-C

deklaracja własności:

@property (weak, nonatomic) NSString *myString; 

Wywołanie @synthesize na nieruchomości:

@synthesize myString = _myString; 

Czy jest jakaś różnica, jeśli chcesz go używać w moim kodu? Gdy? W getter/seter?

self.myString = @"test"; 
_myString = @"test"; 
+0

'self' jest symbolem. '_' jest znakiem w niektórych symbolach. 'myString' i' _myString' to dwa różne symbole, które są powiązane, nie z powodu pisowni, ale dlatego, że są one nazwane w tym samym '@ synthezize'. –

+0

Spróbuj następującą odpowiedź: http://stackoverflow.com/questions/5170631/what-does-synthesize-window-window-do – Peres

+2

Sprawdź, czy @ odpowiedź Jonathana do tego poprzedni SO pytanie pomaga http: // stackoverflow .com/questions/5466496/dlaczego -nazwane-syntezowane-właściwości-in-ios-z wiodącymi-podkreśleniami – visakh7

Odpowiedz

68

self.myString = @"test"; jest dokładnie równoważne pisaniu [self setMyString:@"test"];. Oba wywołują metodę.

Mogłeś sam napisać tę metodę. Może to wyglądać mniej więcej tak:

- (void)setMyString:(NSString*)newString 
{ 
    _myString = newString; 
} 

Ponieważ stosowane @synthesize, nie trzeba faktycznie przeszkadzało pisząc tę ​​metodę, można po prostu pozwolić kompilator do napisania go dla Ciebie.

Tak więc, patrząc na tę metodę, wygląda na to, że wywołanie spowoduje to samo, co właśnie przypisanie wartości zmiennej instancji, prawda? Cóż, to nie takie proste.

Po pierwsze, możesz napisać własną metodę setera. Jeśli to zrobisz, twoja metoda zostanie wywołana i może zrobić wiele dodatkowych rzeczy, jak również ustawić zmienną. W takim przypadku użycie metody self.myString = wywoła tę metodę, ale wykonanie _myString = nie będzie, a zatem będzie używana inna funkcja.

Po drugie, jeśli kiedykolwiek użyjesz Key Value Observing, kompilator zrobi bardzo sprytne sztuczki. Za kulisami podklasuje twoją klasę i nadpisuje twoją metodę ustawiającą (czy to tą, którą sam napisałeś, czy wygenerowaną przez syntezę), aby wykonać połączenia do willChangeValueForKey:, które są potrzebne, aby Key Value Observing działało. Nie musisz wiedzieć, jak to działa (chociaż jest to całkiem interesujące, jeśli chcesz trochę czytać na dobranoc!), Ale musisz wiedzieć, że jeśli chcesz, aby Key Value Observing działało automatycznie, musisz użyć metod setera.

Po trzecie, wywołanie metody ustawiającej, nawet jeśli polegasz na syntezatorze, aby pisać, daje elastyczność na przyszłość. Możesz chcieć zrobić coś ekstra za każdym razem, gdy wartość zostanie zmieniona iw punkcie, w którym odkryjesz, że chcesz to zrobić, możesz ręcznie napisać metodę ustawiającą - jeśli masz zwyczaj używania zawsze self.myString =, to nie będziesz musisz zmienić resztę kodu, aby rozpocząć wywoływanie nowej metody!

Po czwarte, to samo dotyczy podklas. Jeśli ktoś inny miałby podklasować twój kod, jeśli użyjesz setterów, mogliby je przesłonić, by dostosować funkcjonalność.

Za każdym razem, gdy bezpośrednio uzyskujesz dostęp do zmiennej instancji, jawnie nie zapewniasz sposobu na dołączenie dodatkowej funkcjonalności w tym momencie. Ponieważ Ty lub ktoś inny może chcieć skorzystać z takiej funkcjonalności w przyszłości, opłaca się korzystać z ustawiaczy przez cały czas, chyba że jest ku temu dobry powód.

+0

Należy zauważyć, że nie wspomniałem o implikacjach związanych z zarządzaniem pamięcią. Jeśli używasz ARC, są one mniej istotne w tym przypadku, więc pominąłem je. –

+0

Dobre wyjaśnienie :) – iTag

+0

Nawiasem mówiąc, w odniesieniu do pierwszego zdania ... To jest prawda w 99% przypadków, ale jeśli masz własny setter (określony przez 'setter =' w deklaracji właściwości), wtedy te dwa formularze nie są dokładnie równoważne. –

8

Masz rację - pierwsza wersja (self.myString) wywołuje zsyntetyzowany getter/setter a drugi dostępu wersji zmienna członek prywatny bezpośrednio.

Wygląda na to, że używasz ARC, więc w takim przypadku nie robi to wielkiej różnicy. Jeśli jednak nie korzystasz z ARC, może to mieć znaczenie, ponieważ przypisanie bezpośrednio do członka prywatnego nie spowoduje automatycznego wygenerowania logiki zatrzymania/wydania lub kopiowania/wydania za pomocą synthesize.

+0

To dwa różne symbole. Jednym może być "aardvark", a drugi "zebra" i nadal mają związek zmienna-ustawiający/getter. –

+0

@Hot Licks - Masz rację, że nazwy są nieistotne, ale kiedy czytam to pytanie, myślę, że zastanawiał się, jaka jest praktyczna różnica między używaniem zsyntetyzowanej własności a używaniem zmiennej członkowskiej, która ją wspiera. –

+0

@EricPetroelje - tak, dokładnie to, o co prosiłem. Dzięki! – Kuba

3

_ (podkreślenie) to po prostu konwencja, jak wyjaśniono w this question.

Gdy nie prefiksujesz dostępu do właściwości za pomocą self., uzyskujesz bezpośredni dostęp do zmiennej bazowej, jak w c struct. Ogólnie rzecz biorąc, powinieneś to robić tylko w swoich metodach init i niestandardowych akcesoriach. Dzięki temu rzeczy takie jak właściwości obliczone i KVC działają zgodnie z przeznaczeniem.

Powiązane problemy