2012-06-28 7 views
5

lo que es técnicamente incorrecto con lo siguiente:Objective-C propiedad - el comportamiento captador

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

Estoy seguro de que puedo encontrar una mejor manera de organizar esto, pero esto es lo que terminamos con en un momento de mi proyecto y me di cuenta de que acceso a la propiedad horaInicio siempre devuelve 0, incluso cuando la propiedad de marca de tiempo se establece en una fecha y hora correcta.

Parece haber establecido el captador de horaInicio a una propiedad (fecha y hora) existente, no está reenviando el valor de marca de tiempo cuando lo haga:

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

Todas estas son las marcas de tiempo por el camino.

Sólo un recordatorio, sé lo anterior debería haber ocurrido en mi proyecto, pero no entiendo por qué el acceso a horaInicio no reenvía a la propiedad de marca de tiempo.

ACTUALIZACIÓN

En mi aplicación estoy sintetizar todas estas propiedades:

@synthesize timestamp, endTime, startTime; 

Por favor marque un objeto ejemplo de usar que demuestra esto en mi GIST en GitHub: https://gist.github.com/3013951

+0

¿Cuál es el error? Con 'getter'? –

+0

En realidad, mi respuesta fue incorrecta. No importa si tiene múltiples propiedades vinculadas al mismo selector. Diría que no hay problema con esto ... –

+0

@ RichardJ.RossIII Solo realicé mi prueba en el último XCode en un proyecto de ARC. Es posible que esto haya sido un cambio en Clang en algún momento. – Joe

Respuesta

5

En su método de descripción, no está utilizando la propiedad, está accediendo al ivar.

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

Esto funcionará para usted:

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

Lo propiedad-vs-Ivar se mete a la gente todo el tiempo, así que discúlpame mientras yo divagar sobre ello durante un minuto. :) Si ya sabes todo esto, salta hacia adelante.

Al crear y sintetizar una propiedad, como lo hizo anteriormente, suceden dos cosas:

  1. una Ivar se crea del tipo adecuado.
  2. se crea una función getter, que devuelve ese ivar.

La parte importante con respecto al punto 2 es que, por defecto, la Ivar y la función getter (y, por lo tanto, la propiedad) tienen los mismos nombres.

Así que esto:

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

@implementation Event 
@synthesize timestamp, startTime; 
@end 

...se convierte en esto:

@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 

¿Cómo funciona la sintaxis de punto es que esto:

NSUInteger foo = myEvent.startTime; 

realmente

NSUInteger foo = [myEvent startTime]; 

Todo eso quiere decir que cuando se accede a una Ivar, eres ... bueno, accediendo a un ivar. Cuando usa una propiedad, llama a una función que devuelve un valor. Más importante aún, es extremadamente fácil hacer una cosa cuando se refería a la otra, porque la sintaxis es muy similar. Es por esta razón que muchas personas sintetizan rutinariamente sus ivars con guiones bajos destacados, por lo que es más difícil equivocarse.

@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

Por supuesto. lugar perfecto. ¡Era tan simple que era complicado! A veces estás mirando más allá de la superficie y demasiado profundo en algo. Una vez más, una pregunta tonta por mi cuenta ... Gracias por la respuesta. Es interesante notar que usualmente uso la implementación del subrayado, pero por alguna razón esta clase de la mía era muy simple y decidí mantenerla con aún menos código. Lección del día: mantenga su estilo de codificación. Ah, y no hagas preguntas sobre Stack Overflow sin volverte realmente loco – Daniel

1

Asegúrese sintetizas en el orden correcto para que el getter exista para startTime.

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

No presté particular atención al orden de esto, pero resulta que estoy haciendo eso. A menos que deba configurar específicamente la síntesis en una nueva línea. Estoy haciendo @synthesize p1, p2, p3; Tal vez esto no es priorizar las propiedades? – Daniel

+0

¿Qué compilador estás usando? Estoy usando Apple LLVM 3.1 y está funcionando bien para mí. – Joe

+0

Estoy usando lo mismo. Acabo de publicar un enlace a un código de muestra, pruébelo de su lado si es tan amable. – Daniel

Cuestiones relacionadas