2012-06-28 11 views
5

Co jest technicznie tak z następujących powodów:Objective-C nieruchomość - zachowanie getter

@property(nonatomic, assign) NSUInteger timestamp; 
@property(nonatomic, readonly, getter = timestamp) NSUInteger startTime; 
@property(nonatomic, assign) NSUInteger endTime; 

Jestem pewien, że mogę znaleźć lepszy sposób na zorganizowanie tego, ale to, co skończyło się na jednym punkcie mój projekt i zauważyłem, że dostęp do właściwości startTime zawsze zwrócił 0, nawet jeśli właściwość timestamp została ustawiona na poprawny znacznik czasu.

Wydaje Po ustawieniu pochłaniacza startTime do istniejącej nieruchomości (datownik), to nie jest przekazywanie wartości znacznika czasu kiedy zrobić:

event.startTime => 0 
event.timestamp => 1340920893 

Wszystkie te znaczniki czasu na drodze.

Przypominam, wiem, że powyższe powinno się wydarzyć w moim projekcie, ale nie rozumiem, dlaczego dostęp do startTime nie przenosi na właściwość timestamp.

UPDATE

W moim wdrażania jestem syntetyzowania tych wszystkich właściwości:

@synthesize timestamp, endTime, startTime; 

Proszę sprawdzić przykładowy obiekt w obsłudze, że pokazuje to w moim GIST na GitHub: https://gist.github.com/3013951

+0

Jaki jest błąd? Z 'getter'? –

+0

Właściwie moja odpowiedź była błędna. Nie ma znaczenia, czy masz wiele właściwości powiązanych z tym samym selektorem. Powiedziałbym, że nie ma z tym problemu ... –

+0

@ RichardJ.RossIII Przeprowadziłem test tylko w najnowszym XCode w projekcie ARC. Być może była to zmiana w Clangu w pewnym momencie. – Joe

Odpowiedz

5

W swojej metodzie opisu nie korzystasz z właściwości, uzyskujesz dostęp do ivar.

-(NSString*) description 
{ 
    return [NSString stringWithFormat:@"Event< timestamp:%d, start:%d >", 
      timestamp, 
      startTime]; // <-- This is accessing the instance variable, not the property. 
} 

To będzie pracować dla Ciebie:

-(NSString*) description 
{ 
    return [NSString stringWithFormat:@"Event< timestamp:%d, start:%d >", 
      timestamp, 
      self.startTime]; // <-- This is using the property accessor. 
} 

Rzecz nieruchomość-vs-ivar bałagan ludzi cały czas, więc wybacz mi, a ja wędrówka na ten temat na minutę. :) Jeśli już to wszystko wiesz, przejdź dalej.

Po utworzeniu i syntezy nieruchomości, jak to było wyżej, dwie rzeczy:

  1. Ivar jest tworzona od właściwego typu.
  2. Funkcja getter jest tworzona, która zwraca tę wartość.

Ważną częścią o punkcie 2 jest to, że domyślnie na ivar oraz funkcję pochłaniacza (a zatem właściwość) mają takie same nazwy.

Więc tak:

@interface Event 
@property(nonatomic, assign) NSUInteger timestamp; 
@property(nonatomic, readonly, getter = timestamp) NSUInteger startTime; 
@end 

@implementation Event 
@synthesize timestamp, startTime; 
@end 

...zamienia się w ten sposób:

@interface Event { 
    NSUInteger timestamp; 
    NSUInteger startTime; 
} 
@end 

@implementation Event 
- (NSUInteger) timestamp { 
    return timestamp 
} 

- (void) setTimestamp:(NSUInteger) ts { 
    timestamp = ts; 
} 

- (NSUInteger) startTime { 
    return [self timestamp]; 
} 
@end 

Jak kropka składnia działa to, że w ten sposób:

NSUInteger foo = myEvent.startTime; 

naprawdę

NSUInteger foo = [myEvent startTime]; 

Wszystko to znaczy, że podczas dostępu do ivar, jesteś ... cóż, dostęp do ivar. Gdy używasz właściwości, wywołujesz funkcję, która zwraca wartość. Co ważniejsze, bardzo łatwo jest zrobić jedno, gdy chodzi o drugie, ponieważ składnia jest bardzo podobna. Z tego powodu wiele osób rutynowo syntetyzuje swoje ivars z wiodącymi znakami podkreślenia, tak że trudniej jest zepsuć.

@property(nonatomic, assign) NSUInteger timestamp; 
@property(nonatomic, readonly, getter = timestamp) NSUInteger startTime; 

@synthesize timestamp = _timestamp; 
@synthesize startTime = _startTime; 

NSLog(@"startTime = %d", _startTime); // OK, accessing the ivar. 
NSLog(@"startTime = %d", self.startTime); // OK, using the property. 
NSLog(@"startTime = %d", startTime); // NO, that'll cause a compile error, and 
             // you'll say "whoops", and then change it 
             // to one of the above, thereby avoiding 
             // potentially hours of head-scratching. :) 
+0

Oczywiście. na miejscu. To było tak proste, że było skomplikowane! Czasami patrzysz poza powierzchnię i zbyt głęboko w coś. Znów głupie pytanie ... Dziękuję za odpowiedź. Interesujące jest to, że zazwyczaj używam implementacji podkreślenia, ale z jakiegoś powodu ta klasa była bardzo prosta i postanowiłem zachować ją przy jeszcze mniejszym kodzie. Lekcja dnia: Zachowaj swój styl kodowania. Aha, i nie zadawaj pytań na temat Stack Overflow, bez uprzedniego oszalałego – Daniel

1

Upewnij syntetyzujesz we właściwej kolejności, więc getter istnieje dla startTime.

+0

Nie zwracałem szczególnej uwagi na zamawianie tego, ale okazało się, że to robię. Chyba że muszę specjalnie ustawić syntezę w nowej linii. Robię @synthesize p1, p2, p3; Być może nie jest to nie priorytetowe właściwości? – Daniel

+0

Z którego kompilatora korzystasz? Używam Apple LLVM 3.1 i działa dobrze dla mnie. – Joe

+0

Używam tego samego. Właśnie opublikowałem link do przykładowego kodu, przetestuj go po swojej stronie, jeśli byłbyś tak miły. – Daniel