2010-09-27 8 views
15

Próbuję zrozumieć cel dyrektywy synthesize z nadpisaniem nazwy właściwości. Powiedzieć, że mam interfejs zdefiniowany następująco:Objective-C syntetyzuje nadpisanie nazwy właściwości

@interface Dummy ... { 
    UILabel *_dummyLabel; 
} 

@property (retain, nonatomic) UILabel *dummyLabel; 

A w pliku wdrażania, mam:

@synthesize dummyLabel = _dummyLabel; 

Z tego co rozumiem, „dummyLabel” jest tylko aliasem zmiennej instancji " _dummyLabel ". Czy jest jakaś różnica między self._dummyLabel a self.dummyLabel?

Odpowiedz

24

Tak. self._dummyLabel jest niezdefiniowany, jednak nie jest to _dummyLabel.

Składnia punktowa rozszerza się na proste wywołania metod, więc nie jest specyficzna dla właściwości. Jeśli masz metodę o nazwie -(id)someObject, na przykład w przypadku object.someObject, będzie tak, jakbyś napisał [object someObject];.

self.dummyLabel //works 
self._dummyLabel //does not work 
dummyLabel  //does not work 
_dummyLabel  //works 
[self dummyLabel]; //works 
[self _dummyLabel]; //does not work 
+0

Dzięki za szybką odpowiedź. Hm ... okej, czy [self.dummyLabel setText: @ "..."] i [_dummyLabel setText: @ "..."] robią sametowanie? Jeśli tak, nie widzę żadnej dużej korzyści z przemianowania _dummyLabel na dummyLabel. – Thomas

+0

@ Thomas, masz to. –

+1

Zaletą posiadania innej nazwy dla ivar niż dla właściwości jest to, że możesz łatwo zobaczyć w kodzie, gdy uzyskujesz dostęp do jednego lub drugiego. –

17

Twoje zrozumienie jest nieprawidłowe. dummyLabel to nazwa właściwości i jest nie aliasem dla zmiennej instancji - zmienna instancji to tylko o nazwie _dummyLabel. Więc dodaje się trzyma na wystąpienie Dummy zwanego myObject:

  • [myObject dummyLabel] pracuje
  • myObject.dummyLabel działa
  • [myObject _dummyLabel] nie
  • myObject._dummyLabel nie
  • myObject->dummyLabel nie
  • myObject->_dummyLabel zależy od widoczności ivar (@public, @private, @protected)
  • [myObject valueForKey: @"dummyLabel"] działa
  • [myObject valueForKey: @"_dummyLabel"] zależy od realizacji +accessInstanceVariablesDirectly (tj będzie działać w domyślnym przypadku, w którym +accessInstanceVariablesDirectly zwraca YES).
+0

Tak więc, gdy chcę uzyskać dostęp do zmiennej instancji w metodzie, mógłbym użyć '_dummyLabel = @" bla "- a to by zmieniło wartość bezpośrednio, zamiast przechodzić przez setera? Mogę więc mieć właściwość tylko do odczytu bez pośrednika, ale nadal zmieniać ją wewnętrznie, przechodząc od razu do ivar? A jeśli chcę użyć metody getter/setter z metody klasy, po prostu użyłbym 'self.dummyLabel'? Czy mogę też użyć 'dummyLabel' bezpośrednio? –

0

nie widzę każdy Dużą zaletą zmiana nazwy _dummyLabel do dummyLabel

W niektórych ObjC środowisko wykonawcze masz trudny czas podejmowania zmienne instancji niewidoczne dla użytkowników klasy. Dla nich przyklejenie jakiegoś prefiksu (lub sufiksu) na zmiennych instancji może sprawić, że będzie jasne (lub bardziej zrozumiałe), że nie chcesz, aby ktokolwiek bał się ze zmiennymi. Jednak nie chcesz tego gangu w swoich publicznych funkcjach. To pozwala ci to zdjąć.

Może być także przydatny, jeśli zachodzi potrzeba zachowania starego interfejsu z jednym zestawem nazw jednocześnie z nowym zestawem interfejsów API o nowym zestawie nazw (setLastname vs. setSurname).

13

Zaletą posiadania inną nazwę dla ivar niż dla nieruchomości jest które można łatwo zobaczyć w kodzie jeśli dostęp do jednego lub inne - Andre K

I "nie mogę znaleźć przycisku" komentarz ", więc muszę opublikować jako" odpowiedź ".

Po prostu chciałem rozwinąć komentarz Andre - wiedząc, kiedy używasz syntetyzowanych właściwości vs zmienną waniliową, wiesz (szczególnie w przypadku ustawiaczy), kiedy zmienna jest zatrzymywana/kopiowana/wydana automatycznie dzięki twojemu ładnemu seter, a będąc manipulowanym ręcznie.

Oczywiście, jeśli robisz coś dobrze, prawdopodobnie nie potrzebujesz pomocy osoby ustawiającej, aby prawidłowo zachować/uwolnić obiekty! Ale mogą istnieć inne scenariusze, w których odniesienie do twoich ivars jako self.ivar zamiast _ivar może być pomocne, na przykład gdy używasz niestandardowych ustawiaczy/pobierających zamiast domyślnych syntezatorów. Być może za każdym razem, gdy modyfikujesz właściwość, chcesz ją również przechowywać w NSUserDefaults. Więc może masz trochę kodu:

@interface SOUserSettings : NSObject { 

BOOL _autoLoginOn; 

} 

@property (nonatomic, assign) BOOL autoLoginOn; 

@end 

@implementation SOUserSettings 

@synthesize autoLoginOn = _autoLoginOn; 

- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue { 

    _autoLoginOn = newAutoLoginOnValue; 
    [[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"]; 
} 

@end 

Uwaga: To jest tylko kod przykładowy, nie może być tysiąc rzeczy źle z nim!

Teraz, w twoim kodzie, jeśli masz linię, która mówi: _autoLoginOn = YES - wiesz, że nie zostanie zapisana w NSUserDefaults, natomiast jeśli używasz self.autoLoginOn = YES, wiesz dokładnie, co się stanie.

Różnica między _autoLoginOn a self.autoLoginOn jest czymś więcej niż semantycznym.

+0

Dobrze, że o tym wspomniałeś! Rzeczywiście istnieje różnica! –

0

Stary post, ale myślę, że ważne jest, aby wspomnieć, że zaleca się dostęp do zmiennych za pomocą modułów pobierających i ustawiających (czyli z notacją kropkową). Uzyskiwanie dostępu do pola bezpośrednio (_ivar) jest zalecane tylko podczas jego inicjowania.

Jest jakiś dobry artykuł Apple: https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

ostatni akapit:

Należy zawsze uzyskać dostęp do zmiennych instancji bezpośrednio z metoda inicjalizacji, ponieważ w czasie, gdy nieruchomość jest ustawiony, reszta obiektu może jeszcze nie zostać całkowicie zainicjalizowana. Nawet jeśli użytkownik nie zapewnia niestandardowych metod dostępu lub nie zna żadnych efektów ubocznych z w obrębie własnej klasy, przyszłej podklasy może bardzo dobrze nadpisać zachowanie .

Powiązane problemy