2013-01-01 9 views
7

Powiel możliwe:
How does an underscore in front of a variable in a cocoa objective-c class work?self.variableName vs. _variableName vs. @sysnthesize variableName


Uwaga: Dla ludzi kopiących wokół próbując zrozumieć to, I wymyśliłem źródło mego zamieszania. W .h, miałem:

... 
@interface myClass : parentClass { 
className *variableName: 
} 

@property (strong, nonatomic) className *variableName; 
... 

Prowadzi to do self.variableName i _variableName są dwie różne zmienne w .m. Co mi było potrzebne:

... 
@interface myClass : parentClass { 
className *_variableName: 
} 

@property (strong, nonatomic) className *variableName; 
... 

Następnie w klasie .m, self.variableName i _variableName są równoważne


W nowy, Xcode 4.5+, z ARC, kierowanie iOS 5.0 + projekt, czy istnieje wyraźna przewaga (wydajność, prędkość, itp.) do używania _variableName przez self.variableName w porównaniu ze starym stylem @synthesize variableName?

Rozumiem, że Xcode 4.5+ stworzy domyślny akcesor _variableName który jest odpowiednikiem self.variableName i jedyne powody, aby nie używać @synthesize variableName jest uniknięcie mylenia Ivars i przekazywane w zmiennych, prawda?

Dla mnie użycie tylko self.variableName w celu uzyskania dostępu do iVar wydaje się być najprostsze i jasne, jakiej zmiennej szukasz. Inne niż wpisywanie _ vs. self., czy istnieje korzyść z używania _variableName?

+1

A oto kolejny 16: http://stackoverflow.com/q/5582448/ http://stackoverflow.com/q/6049269/ http://stackoverflow.com/q/2371489/ http://stackoverflow.com/q/7174277/ http://stackoverflow.com/q/5659156 http://stackoverflow.com/q/837559/ http://stackoverflow.com/q/6146244/ http: //przepełnienie stosu.com/q/10651535/ http://stackoverflow.com/q/6124109/ http://stackoverflow.com/q/8145373/ http://stackoverflow.com/q/3521254/ http: // stackoverflow.com/q/6064283/ http://stackoverflow.com/q/9696359/ http://stackoverflow.com/q/5521499/ http://stackoverflow.com/q/5466496/ http: //stackoverflow.com/q/2114587/ –

+0

Moja zła. Nie myślę o szukaniu podkreślenia. To powiedziawszy, sprawdzając kilka potencjalnych duplikatów, nie zauważyłem żadnej wzmianki o ewentualnych problemach z obserwacjami kluczowymi, wiązaniami i dostępem do wątków (atomowych), jeśli używa się _variableName vs. self .variableName. Jeden (4088801) wspomniał o potencjalnym problemie, jeśli obiekt, o którym mowa w _variableName, jest współużytkowany i zalecany przy użyciu self.variableName. –

+0

Jeśli zauważysz konkretny problem, który został pominięty w jednym z wielu wystąpień ogólnego pytania, z pewnością powinieneś o niego zapytać szczegółowo. Nie ma jednak żadnej wartości, jeśli informacje te zostaną pochowane w jeszcze jednej kopii. –

Odpowiedz

15

Rozumiem, że Xcode 4.5+ stworzy domyślny akcesor „_variableName”, który jest odpowiednikiem self.variableName i jedynych powodów, aby nie używać „@synthesize variableName” ma na celu uniknięcie mylenia Ivars i przekazywane w zmienne, poprawne?

W tym przypadku nie jest _variableName Akcesor, jest to Ivar, który jest automatycznie generowany przez kompilator i wykorzystywane w automatycznie @synthesized ustawiające i pochłaniacze. Zasadniczo najlepiej jest używać akcesorów, gdy tylko jest to możliwe (np. self.variableName), aby rzeczy takie jak obserwacje i powiązania w postaci wartości klucza i powiązania działały dla tej właściwości.

Bezpośredni dostęp do ivar jest możliwy poprzez bezpośredni dostęp do pamięci, w ten sam sposób, w jaki dostęp do danych w strukturze. Po prostu pobiera wskaźnik dla obiektu, który jest właścicielem ivar, przesuwa adres pamięci i próbuje odczytać lub zapisać w pamięci w tej lokalizacji. Notacji kropki (self.variableName) wywołuje metody dostępowe do ustawienia lub uzyskać tę właściwość i może zrobić wiele różnych rzeczy po drodze, takie jak:

1) Blokowanie: Jeżeli nieruchomość ma być stosowany w wiele wątków i jest to właściwość atomic, środowisko wykonawcze automatycznie wykona blokowanie, aby upewnić się, że właściwość nie jest dostępna w tym samym czasie z wielu wątków. Jeśli twój obiekt nie jest przeznaczony do używania w wielu wątkach, możesz podać wskazówkę nonatomic w deklaracji właściwości, aby syntezowane dodatki pomijały blokowanie.

2) klucz-wartość Powiadomienia: Domyślnym ustawiaczy dla właściwości zadzwonić -willChangeValueForKey: i -didChangeValueForKey:, który wysyła informację, gdy właściwość została zmieniona. Jest to konieczne, aby cokolwiek zaktualizować poprawnie, jeśli używane są wiązania i dla każdej innej obserwacji klucz-wartość.

3) niestandardowe zachowanie accessor: Jeśli kończy się pisania własnych ustawiające i pobierające, wszelkie niestandardowe rzeczy, które możesz wdrożyć w ciągu tych.

Technicznie, bezpośredni dostęp do ivar jest szybszy niż korzystanie z akcesorów, ale jest bardzo niewiele sytuacji, w których spowoduje znaczną różnicę w wydajności i prawdopodobnie będzie to przypadek przedwczesnej optymalizacji. Nawet jeśli nie masz ochoty na korzystanie z wyżej wymienionych korzyści, prawdopodobnie lepiej będzie użyć akcesorów, więc jeśli później zdecydujesz, że potrzebujesz tej funkcji, nie musisz zmieniać każdego wystąpienia dostępu do tej zmiennej (i prawdopodobnie tworzenie nieoczekiwanych nowych błędów w procesie).

Ponadto, jeśli masz dostęp Ivars bezpośrednio i skończyć refactoring swoją klasę na kategorie lub podklasy, robi się bałagan, bo zwykle trzeba zadeklarować ivar jako zmienną @protected. Nie musisz tego robić, jeśli używasz akcesorów.

Ogólnie próbuję uzyskać dostęp do ivars tylko bezpośrednio w init, dealloc i akcesoru właściwości. Wielu inżynierów stosuje się do tej reguły, ponieważ czasami niestandardowe elementy występujące w akcesoriach mogą powodować nieoczekiwane zachowanie, podczas gdy obiekt jest obiektem. Na przykład, jeśli w ogóle w dostępowych powoduje coś retain lub release obiektu lub nawet tworzyć zerowania słabe odniesienie do niego, spowoduje to awarię, jeżeli są stosowane w dealloc.

5

W najnowszym Xcode @synthesize jest opcjonalne. Domyślnie, pomijając @synthesize jest taka sama jak pisanie

@synthesize someName = _someName; 

jedyny powód do korzystania @synthesize jest przemianować do instancji zmiennej stworzony do przechowywania wartości nieruchomości, na przykład

@synthesize someName = someSpecialName; 

Kiedy używasz self.variableName, aby uzyskać dostęp do zmiennej, przechodzisz przez właściwość, która jest krótką metodą, która uzyskuje dostęp do zmiennej instancji. Mimo że wysyłka metody jest bardzo szybka, może wykonać dla ciebie dodatkowe usługi, takie jak synchronizacja dostępu do zmiennej (tak jest w przypadku określania atomic lub nie określaj nonatomic w deklaracji właściwości). W takich przypadkach dostęp przez self.variableName będzie nieco wolniejszy. Jeśli zostanie zrobione w ciasnej pętli, może to potencjalnie zmienić sytuację. Dlatego czasami chcesz uzyskać dostęp do bazowej zmiennej instancji bezpośrednio, korzystając z _variableName.

+0

Po prostu bycie pedantycznym, opartym na Twojej odpowiedzi i @eyebrowsoffire, _variableName, może być szybsze, ale self.variableName jest bezpieczniejsze? –

+0

@RayatERISCorp "Safer" jest niedookreślony w tym kontekście, ale jeśli twoim zamiarem było użycie właściwości w zsynchronizowany sposób (tj. Jest to atomowy), odpowiedź brzmi: tak, jest bezpieczniejsza. W rzeczywistości, inny sposób (tj. Przejście na "_variableName" bezpośrednio) po prostu nie działa bez dodatkowego blokowania. – dasblinkenlight

+0

Gotcha. Przez "bezpieczniejsze" rozumiem "mniej prawdopodobne, że uruchomię jakiś nieoczekiwany błąd w moim kodzie, który pozostawi mnie do debugowania na dłużej niż powinienem, ponieważ użycie _variableName nie automagicznie uruchamia pewne działanie, które robi self.variableName." –