2009-05-18 21 views
5

Dada la siguiente definición de una clase con propiedades retener:¿Por qué esta propiedad necesita el 'retener'?

@interface FeedEntry : NSObject<NSCoding> 
{ 
    NSURL* url; 
    NSData* source; 
} 

@property (retain) NSURL* url; 
@property (retain) NSData* source; 
@end 

@implementation FeedEntry 

@synthesize url; 
@synthesize source; 

-(void)encodeWithCoder:(NSCoder*)coder 
{ 
    [coder encodeObject:url  forKey:@"url"]; 
    [coder encodeObject:source forKey:@"source"]; 
} 

¿Por qué la propiedad url en el método initWithCoder necesitan el "mantener":

-(id)initWithCoder:(NSCoder*)coder 
{ 
    url = [[coder decodeObjectForKey:@"url"] retain]; 
    source = [coder decodeObjectForKey:@"source"]; 

    NSLog(@"got url=%@\n", url); 
    return self; 
} 

Específicamente, ¿por qué no la sintetiza " obtener el método "url" retener el objeto? (Supongo que la propiedad fuente también necesitará un retener).

Respuesta

16

respuesta rápida:

cuando se establece:

url = [[coder decodeObjectForKey:@"url"] retain]; 

son no utilizando el @property. Está configurando manualmente el valor de la variable de instancia url. Debe, por lo tanto, también manualmente retain el valor.

para establecer la variable usando las propiedades sintetizados, debe en su lugar llamar:

[self setUrl:[coder decodeObjectForKey:@"url"]]; 

o

self.url = [coder decodeObjectForKey:@"url"]; 

Cualquiera de estas formas podría hacer uso de los métodos de síntesis, y manejar la retain automáticamente .

Detalles:

En Objective-C, los @property y @synthesize palabras clave crean automáticamente los métodos get y set para usted:

@interface MyClass 
{ 
    id someValue; 
} 
@property (retain) id someValue; 
@end 

@implementation MyClass 
@synthesize someValue; 
@end 

es equivalente a:

@interface MyClass 
{ 
    id someValue; 
} 
- (id)someValue; 
- (void)setSomeValue:(id)newValue; 
@end 

@implementation MyClass 
- (id)someValue { return someValue; } 
- (void)setSomeValue:(id)newValue 
{ 
    [newValue retain]; 
    [someValue release]; 
    someValue = newValue; 
} 
@end 

Esto crea una distinción importante entre la variable miembro "interna" y la propiedad que tiene el mismo nombre. Si hace referencia a la variable miembro por su nombre, está pasando por alto los métodos de propiedad sintetizada.

+0

¡De hecho! Tengo la sensación de que esto me morderá con bastante frecuencia. Gracias por su respuesta. – Justicle

+0

Mi placer. Toma un tiempo acostumbrarse, al principio. Una vez que lo has estado haciendo por un tiempo, se convierte en una segunda naturaleza :) –

+4

Esa es una de las razones por las que me gusta utilizar un prefijo _ en variables de instancia privadas, hace que sea muy fácil saber cuándo estás usando una variable de instancia contra todo lo demás. –

Cuestiones relacionadas