iphone - framework - cocoa touch español
Propiedad vs. variable de instancia (7)
El problema con el uso de la estrategia @synthesize myVar = _myVar es que creo que escribir código como:
myVar = some_other_object; // doesn''t work.
El compilador se queja de que
myVar
no está declarado. ¿Por qué es ese el caso?
Porque la variable myVar
no está declarada.
Esa declaración usa la sintaxis para acceder a una variable, ya sea una variable de instancia o algún otro tipo. Como le dijo rincewind, para acceder a una propiedad, debe usar la sintaxis de acceso a la propiedad ( self.myVar = someOtherObject
) o un mensaje explícito al método del [self setMyVar:someOtherObject]
( [self setMyVar:someOtherObject]
).
De lo contrario, está intentando acceder a una variable, y como no tiene una variable llamada myVar
, está intentando acceder a una variable que no existe.
Intento entender cómo estrategias usan algunas personas para distinguir los valores de instancia vs. propiedades. Un patrón común es el siguiente:
@interface MyClass : NSObject {
NSString *_myVar;
}
@property (nonatomic, retain) NSString *myVar;
@end
@implementation MyClass
@synthesize myVar = _myVar;
Ahora, pensé que toda la premisa detrás de esta estrategia es que uno puede distinguir fácilmente la diferencia entre un ivar y la propiedad. Entonces, si quiero usar la administración de memoria heredada por una propiedad sintetizada, usaría algo como:
myVar = @"Foo";
La otra forma sería hacer referencia a ella a través de uno mismo. [Ivar / propiedad aquí].
El problema con el uso de la estrategia @synthesize myVar = _myVar es que creo que escribir código como:
myVar = some_other_object; // doesn''t work.
El compilador se queja de que myVar no está declarado. ¿Por qué es ese el caso?
Gracias.
¿Qué pasa con simplemente usar
@interface MyClass : NSObject
@property NSString *prop;
@end
nonatomic y reten no son necesarios, retener es el predeterminado, y atomic / nonatomic isn / t important a menos que XCode te lo diga con una advertencia.
NO es necesario declarar el iVar, se creará uno para usted llamado _prop, si realmente quiere usar uno (no veo por qué ser honesto)
@synthesize NO es obligatorio.
cuando (y deberías) usar ARC, no tienes que molestarte en retener y liberar ninguno.
mantenlo simple !
Además, si tienes un método como este
- (void)aMethod:(NSString*)string
{
self.prop = string;
// shows very clearly that we are setting the property of our object
_aName = string;
// what is _aName ? the _ is a convention, not a real visual help
}
siempre usaría propiedades, más flexible, más fácil de leer.
Como Apple se reserva el prefijo _ y, como prefiero hacerlo más obvio cuando estoy usando el setter y cuando estoy usando el ivar, he adoptado la práctica de usar un prefijo de i_ en mis ivars, así que por ejemplo :
@interface MyClass : NSObject {
NSString *i_myVar;
}
@property (nonatomic, retain) NSString *myVar;
@synthesize myVar = i_myVar;
i_myVar = [input retain];
self.myVar = anotherInput;
[i_myVar release]
Dado que es muy importante saber cuándo está usando el setter y cuándo está usando el ivar, encuentro que el nombre explícitamente diferente es más seguro.
En tu pregunta, debería ser:
self.myVar = @"Foo"; // with setter, equivalent to [self setMyVar:@"Foo"]
y
_myVar = some_other_object; // direct ivar access - no memory management!
Recuerde que no debe usar setters / getters en init / dealloc, por lo que debe hacer su acceso directo a ivar (y una cuidadosa administración de memoria) en esos métodos.
Don,
De acuerdo con las "reglas", debe llamar a la Versión para cada Copia, Alloc y Retener. Entonces, ¿por qué llamas a Release sobre cosas? ¿Es esto asumiendo que fue creado utilizando Alloc, Copy o Retain?
Esto nos lleva a otra pregunta: ¿es dañino llamar a Release sobre una referencia a un objeto si ya se ha lanzado?
En general, nombro mis propiedades igual que mis variables de instancia; esta es la suposición predeterminada que hace la sintaxis @property
. Si encuentra que está luchando contra los valores predeterminados, lo está haciendo mal (o su plataforma de sux, que no es el caso de Cocoa / Cocoa-touch en mi opinión).
El error de compilación que está obteniendo es porque el uso de la propiedad siempre debe tener una referencia de objeto, incluso dentro de su propia implementación de clase:
self.stuff = @"foo"; // property setter
[stuff release]; // instance variable
stuff = @"bar"; // instance variable
return self.stuff; // property getter
Sé que muchos programadores de Cocoa no están de acuerdo, pero creo que es una mala práctica usar propiedades dentro de la implementación de su clase. Prefiero ver algo como esto:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
[stuff release];
stuff = [theStuff copy];
// do something else
}
que esto:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
self.stuff = theStuff;
// do something else
}
Prefiero hacer la gestión de la memoria lo más explícitamente posible. Pero incluso si no está de acuerdo, usar el formulario self.stuff
indicará en cualquier programador experimentado de Objective-C que está llamando una propiedad en lugar de acceder a una variable de instancia. Es un punto sutil que es fácil para los principiantes pasar por alto, pero después de que hayas trabajado con Objective-C 2.0 por un tiempo, está bastante claro.
Las propiedades son solo setters y getters para ivars
y deberían (casi) siempre usarse en lugar de acceso directo.
@interface APerson : NSObject {
// NSString *_name; // necessary for legacy runtime
}
@property(readwrite) NSString *name;
@end
@implementation APerson
@synthesize name; // use name = _name for legacy runtime
@end
@synthesize
crea en este caso esos dos métodos (no es 100% exacto):
- (NSString *)name {
return [[_name copy] autorelease];
}
- (void)setName:(NSString *)value {
[value retain];
[_name release];
_name = value;
}
Ahora es fácil distinguir entre ivars
y getters / setters. Los usuarios se han self.
prefijo. No debe acceder a las variables directamente de todos modos.
Su código de muestra no funciona como debería ser:
_myVar = some_other_object; // _myVar is the ivar, not myVar.
self.myVar = some_other_object; // works too, uses the accessors
Una propiedad sintetizada llamada prop
se representa en realidad por dos métodos prop
(que devuelve el valor actual de la propiedad) y setProp:
(establece un nuevo valor para prop).
La sintaxis de self.prop
es azúcar sintáctica para llamar a uno de estos self.prop
. En su ejemplo, puede hacer cualquiera de los siguientes para configurar la propiedad myVar
:
self.myVar = @"foo"; // handles retain/release as specified by your property declaration
[self setMyVar: @"foo"]; // handle retain/release
_myVar = @"Foo"; // does not release old object and does not retain the new object
Para acceder a las propiedades, use self.propname
. Para acceder a las variables de instancia, use solo el nombre de la variable de instancia.