Po co zmieniać nazwy syntetyzowanych właściwości w iOS z wiodącymi podkreślnikami? [duplikat]

Możliwy duplikat:
Jak działa podkreślenie przed zmienną w klasie Cocoa objective-c?

[4]} podczas tworzenia nowego projektu w Xcode 4, Kod boilerplate dodaje znak podkreślenia, gdy syntetyzuje ivars w pliku implementacji jako:
@synthesize window = _window;

Lub:

@synthesize managedObjectContext = __managedObjectContext;
Czy ktoś może mi powiedzieć, co tu się osiąga? Nie jestem kompletnym nube, ale to jest jeden aspekt objective-C, którego nie rozumiem.

Kolejny punkt zamieszania; w implementacji delegata aplikacji, po zsyntetyzowaniu window iVar jak powyżej, w metodzie didFinishLaunchingWithOptions: do ivarów window I viewController odnoszą się używając self:

self.window.rootViewController = self.viewController
[self.window makeKeyAndVisible];

Ale w metodzie dealloc jest to _window lub _viewController

Thanks

Author: Community, 2011-03-29

4 answers

Jest to artefakt poprzedniej wersji runtime Objective-C.

Pierwotnie, @synthesize było używane do tworzenia metod dostępu, ale runtime nadal wymagało, aby zmienne instancji musiały być bezpośrednio utworzone:

@interface Foo : Bar {
  Baz *_qux;
}

@property (retain) Baz *qux;
@end

@implementation Foo
@synthesize qux = _qux;

- (void)dealloc {
  [_qux release];
  [super dealloc];
}

@end

Ludzie określaliby swoje zmienne instancji, aby odróżnić je od ich właściwości (nawet jeśli Apple nie chce, abyś używał podkreślników, ale to inna sprawa). Można zsyntetyzować właściwość, aby wskazać zmienną instancji. Chodzi jednak o to, że _qux jest zmienną instancyjną, a self.qux (lub [self qux]) jest wiadomością qux wysłaną do obiektu self.

Używamy zmiennej instancji bezpośrednio w -dealloc; użycie metody accessor zamiast tego wyglądałoby tak (choć nie polecam jej, z powodów wyjaśnię krótko):

- (void)dealloc {
  self.qux = nil; // [self setQux:nil];
  [super dealloc];
}

Powoduje to zwolnienie qux, a także zerowanie odniesienia. Ale to może mieć niefortunne skutki uboczne:

  • możesz skończyć strzelając nieoczekiwane powiadomienia. Inne obiekty mogą obserwować zmiany qux, które są rejestrowane, gdy do ich zmiany używana jest metoda accessora.
  • (nie wszyscy się z tym zgadzają:) Zerowanie wskaźnika tak, jak robi to accessor, może ukryć błędy logiczne w twoim programie. Jeśli kiedykolwiek uzyskujesz dostęp do zmiennej instancji obiektu po obiekt został dealokowany, robisz coś poważnie złego. Ze względu na semantykę Objective-C nil - messaging, będziesz nigdy nie wiadomo, po użyciu accesora do Ustawienia na nil. Gdybyś zwolnił zmienną instancyjną bezpośrednio i nie wyzerował referencji, dostęp do dealokowanego obiektu spowodowałby głośny EXC_BAD_ACCESS.

Późniejsze wersje runtime dodały możliwość syntezy zmiennych instancji oprócz metod accessora. W tych wersjach runtime powyższy kod można zapisać pomijając zmienne instancji:

@interface Foo : Bar
@property (retain) Baz *qux;
@end

@implementation Foo
@synthesize qux = _qux;

- (void)dealloc {
  [_qux release];
  [super dealloc];
}

@end

To rzeczywiście syntetyzuje instancję zmienna na Foo o nazwie _qux, do której dostęp mają komunikaty getter i setter -qux i -setQux:.

Polecam przed tym: JEST Trochę bałagan, ale jest jeden dobry powód, aby użyć podkreślenia; a mianowicie, aby chronić przed przypadkowym bezpośrednim dostępem ivar. Jeśli uważasz, że możesz sobie zaufać, że zapamiętasz, czy używasz surowej zmiennej instancji, czy metody accessora, zrób to w ten sposób:

@interface Foo : Bar
@property (retain) Baz *qux;
@end

@implementation Foo
@synthesize qux;

- (void)dealloc {
  [qux release];
  [super dealloc];
}

@end

Wtedy, gdy chcesz uzyskać bezpośredni dostęp do zmiennej instancji, po prostu powiedz qux (co tłumaczy się na self->qux w składni C, aby uzyskać dostęp do elementu ze wskaźnika). Jeśli chcesz korzystać z metod accessors (które będą powiadamiać obserwatorów i robić inne ciekawe rzeczy, a także uczynić rzeczy bezpieczniejszymi i łatwiejszymi w zakresie zarządzania pamięcią), użyj self.qux ([self qux]) oraz self.qux = blah; ([self setQux:blah]).

Smutne jest to, że przykładowy kod Apple ' a i kod szablonu są do bani. Nigdy nie używaj go jako przewodnika po właściwym stylu Objective-C, a na pewno nigdy nie używaj go jako przewodnika po właściwym Architektura oprogramowania. :)

 223
Author: Jonathan Sterling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-13 17:54:46

Jest jeszcze jeden powód. Bez podkreślenia zmiennych instancji często otrzymuje się ostrzeżenie o parametrach self.title = title i self.rating = rating:

@implementation ScaryBugData
@synthesize title;
@synthesize rating;
- (id)initWithTitle:(NSString *)title rating:(float)rating {
    if (self = [super init]) {
        self.title = title; // Warning. Local declaration hides instance variable
        self.rating = rating; // Warning. Local declaration hides instance variable
    }
    return self;
}
@end

Unikasz Ostrzeżenia, podkreślając zmienne instancji:

@implementation ScaryBugData
    @synthesize title = _title;
    @synthesize rating = _rating;
    - (id)initWithTitle:(NSString *)title rating:(float)rating {
        if (self = [super init]) {
            self.title = title; // No warning
            self.rating = rating; // No warning
        }
        return self;
    }
    @end
 13
Author: Freeman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 15:17:59

W aplikacji didFinishLaunchingWithOptions: method do ivarów window i viewController odnoszą się za pomocą self

Nie, Nie są. Są to odniesienia do właściwości window i viewController. To jest punkt podkreślenia, aby wyjaśnić, kiedy właściwość jest używana (bez podkreślenia) i kiedy ivar jest dostępny bezpośrednio (z podkreśleniem).
 6
Author: LaC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-29 00:25:06

Tak, Its jest tylko po to, aby odróżnić odniesienie do obiektu. Oznacza to, że jeśli obiekt jest bezpośrednio referowany, użyj go z podkreśleniem, w przeciwnym razie użyj self, aby odnieść się do obiektu.

 2
Author: Krishna Kishore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-30 04:38:40