framework español iphone objective-c cocoa cocoa-touch

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.