2012-06-28 27 views
5

Qual è tecnicamente sbagliato con il seguente:Objective-C Proprietà - comportamento getter

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

Sono sicuro di poter trovare un modo migliore per organizzare questo, ma questo è quello che ho finito con ad un certo punto il mio progetto e ho notato che l'accesso alla proprietà startTime restituiva sempre 0, anche quando la proprietà timestamp era impostata su un timestamp corretto.

sembra aver impostato il getter di startTime a una proprietà (timestamp) esistente, non inoltra il valore del timestamp quando lo faccio:

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

Tutti questi sono timestamp per la via.

Solo un promemoria, so che quanto sopra dovrebbe essere successo nel mio progetto ma non capisco perché l'accesso a startTime non inoltra la proprietà timestamp.

UPDATE

Nella mia applicazione sto sintetizzare tutte queste proprietà:

@synthesize timestamp, endTime, startTime; 

prega di controllare un oggetto esempio per utilizzare che illustra questo al mio succo su GitHub: https://gist.github.com/3013951

+0

Qual è l'errore? Con 'getter'? –

+0

In realtà, la mia risposta era sbagliata. Non importa se hai più proprietà collegate allo stesso selettore. Direi che non c'è alcun problema con questo ... –

+0

@ RichardJ.RossIII Ho eseguito il mio test solo nell'ultimo XCode in un progetto ARC. Potrebbe essere possibile che questo fosse un cambiamento in Clang ad un certo punto. – Joe

risposta

5

Nel metodo della descrizione, non si sta utilizzando la proprietà, si sta accedendo a ivar.

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

Questo funziona per voi:

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

La cosa proprietà-vs-Ivar scombina la gente per tutto il tempo, così mi scusi, mentre io divagare a questo proposito per un minuto. :) Se già conosci tutto questo, salta.

Quando si crea e sintetizzare una proprietà, come avete fatto in precedenza, accadono due cose:

  1. un Ivar è creato del tipo corretto.
  2. viene creata una funzione getter, che restituisce tale ivar.

La parte importante attorno al punto 2 è che, per default, l'ivar e la funzione getter (e quindi, la proprietà) hanno gli stessi nomi.

Quindi questo:

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

@implementation Event 
@synthesize timestamp, startTime; 
@end 

...si trasforma in questo:

@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 

Come funziona la sintassi del punto è che questo:

NSUInteger foo = myEvent.startTime; 

fa davvero

NSUInteger foo = [myEvent startTime]; 

Tutto questo per dire che quando si accede a un Ivar, sei ... beh, accedendo a un ivar. Quando si utilizza una proprietà, si chiama una funzione che restituisce un valore. Ancora più importante, è estremamente facile fare una cosa quando si intende l'altra, perché la sintassi è molto simile. È per questo motivo che molte persone sintetizzano abitualmente i loro ivar con i caratteri di sottolineatura principali, quindi è più difficile incasinare.

@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

Ovviamente. spot on. Era così semplice che era complicato! A volte stai guardando oltre la superficie e troppo in profondità in qualcosa. Di nuovo una domanda sciocca da solo ... Grazie per la risposta. È interessante notare che di solito uso l'implementazione del trattino basso, ma per qualche motivo questa mia classe era molto semplice e ho deciso di tenerlo con un codice ancora meno. Lezione del giorno: mantieni il tuo stile di codifica. Oh e non fare domande su Stack Overflow senza prima essere veramente pazzo – Daniel

1

Assicurarsi sintetizzare nell'ordine corretto in modo che esista il getter per startTime.

//implementation 
@synthesize timestamp; 
@synthesize statTime; 
+0

Non ho prestato particolare attenzione all'ordinamento di questo, ma risulta che lo sto facendo. A meno che non sia necessario impostare in modo specifico la sintesi su una nuova riga. Sto facendo @synthesize p1, p2, p3; Forse questo non è non dare la priorità alle proprietà? – Daniel

+0

Quale compilatore stai usando? Sto usando Apple LLVM 3.1 e sta funzionando bene per me. – Joe

+0

Sto usando lo stesso. Ho appena postato un link ad un codice di esempio, per favore testalo dalla tua parte se saresti così gentile. – Daniel

Problemi correlati