¿Hay alguna diferencia entre una "variable de instancia" y una "propiedad" en Objective-c?
No estoy muy seguro de esto. Creo que una "propiedad" es una variable de instancia que tiene métodos de acceso, pero podría pensar mal.
Respuestas:
Una propiedad es un concepto más abstracto. Una variable de instancia es literalmente solo una ranura de almacenamiento, como una ranura en una estructura. Normalmente, se supone que otros objetos nunca deben acceder a ellos directamente. Una propiedad, por otro lado, es un atributo de su objeto al que se puede acceder (suena vago y se supone que debe hacerlo). Por lo general, una propiedad devolverá o establecerá una variable de instancia, pero podría usar datos de varias o ninguna. Por ejemplo:
@interface Person : NSObject {
NSString *name;
}
@property(copy) NSString *name;
@property(copy) NSString *firstName;
@property(copy) NSString *lastName;
@end
@implementation Person
@synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:@" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:@" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:@" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:@" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:@" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:@" "];
}
@end
(Nota: El código anterior tiene errores, ya que asume que el nombre ya existe y tiene al menos dos componentes (por ejemplo, "Bill Gates" en lugar de solo "Gates"). Sentí que corregir esas suposiciones haría que el verdadero objetivo del código menos claro, así que solo lo señalo aquí para que nadie repita inocentemente esos errores).
Una propiedad es una forma amigable de implementar un getter / setter para algún valor, con características y sintaxis útiles adicionales. Una propiedad puede estar respaldada por una variable de instancia, pero también puede definir el getter / setter para hacer algo un poco más dinámico, por ejemplo, puede definir una propiedad lowerCase en una cadena que crea dinámicamente el resultado en lugar de devolver el valor de algún miembro. variable.
He aquí un ejemplo:
// === In your .h ===
@interface MyObject {
NSString *propertyName;
}
// ...
@property (nonatomic, retain) NSString *propertyName;
// === In your .m @implementation ===
@synthesize propertyName /* = otherVarName */;
La @property
línea define una propiedad llamada propertyName
de tipo NSString *
. Esto se puede obtener / configurar usando la siguiente sintaxis:
myObject.propertyName = @"Hello World!";
NSLog("Value: %@", myObject.propertyName);
Cuando asigna o lee de myObject.propertyName
, realmente está llamando a métodos setter / getter en el objeto.
La @synthesize
línea le dice al compilador que genere estos getter / setters por usted, usando la variable miembro con el mismo nombre de la propiedad para almacenar el valor (o otherVarName
si usa la sintaxis en los comentarios).
Junto con @synthesize
, aún puede anular uno de los getter / setters definiendo el suyo. La convención de nomenclatura para estos métodos es setPropertyName:
para el setter y propertyName
(o getPropertyName
no estándar) para el getter. El otro todavía se generará para ti.
En su @property
línea, puede definir una serie de atributos en parens para la propiedad que pueden automatizar cosas como la seguridad de subprocesos y la gestión de memoria. Por defecto, una propiedad es atómica, lo que significa que el compilador ajustará las @synthesiz
llamadas get / set con los bloqueos adecuados para evitar problemas de concurrencia. Puede especificar el nonatomic
atributo para deshabilitarlo (por ejemplo, en el iPhone al que desea asignar la mayoría de las propiedades por defecto nonatomic
).
Hay 3 valores de atributo que controlan la gestión de la memoria para cualquier @synthesized
configurador. La primera es la retain
que se enviará automáticamente release
a los valores antiguos de la propiedad y retain
a los nuevos valores. Esto es muy útil.
El segundo es copy
que hará una copia de los valores pasados en lugar de retenerlos. Es una buena práctica usar copy
para NSString porque una persona que llama podría pasar un NSMutableString y cambiarlo por debajo de usted. copy
hará una nueva copia de la entrada a la que solo usted tiene acceso.
El tercero es assign
cuál asigna un puntero directo sin llamar a retener / liberar en el objeto antiguo o nuevo.
Por último, también puede utilizar el readonly
atributo para deshabilitar el establecedor de la propiedad.
Utilizo propiedades para la parte de la interfaz, donde el objeto interactúa con otros objetos y las variables de instancia son cosas que necesita dentro de su clase, se supone que nadie más que usted debe verlas y manipularlas.
De forma predeterminada, una propiedad de lectura y escritura estará respaldada por una variable de instancia, que nuevamente será sintetizada automáticamente por el compilador.
Una variable de instancia es una variable que existe y mantiene su valor durante la vida del objeto. La memoria utilizada para las variables de ejemplo se asigna cuando el objeto se crea por primera vez (a través de alloc) y se libera cuando el objeto se desasigna.
A menos que especifique lo contrario, la variable de instancia sintetizada tiene el mismo nombre que la propiedad, pero con un prefijo de subrayado. Para una propiedad llamada firstName, por ejemplo, la variable de instancia sintetizada se llamará _firstName.
Anteriormente, la gente usaba propiedades públicamente y ivars para uso privado, pero desde hace varios años, también puede definir propiedades @implementation
para usarlas de forma privada. Pero todavía usaría ivars cuando sea posible, ya que hay menos letras para escribir y se ejecuta más rápido de acuerdo con este artículo . Tiene sentido ya que las propiedades están destinadas a ser "pesadas": se supone que se debe acceder a ellas desde getters / setters generados o desde los escritos manualmente.
Sin embargo, en los códigos recientes de Apple, los ivars ya no se utilizan. Supongo que porque es más como objc
lugar de C/C++
, además de que es más fácil de usar con propiedades assign
, nullable
etc.
@implementation
quiere mostrar similitudes con Swift. Aún así, también prefiero respaldar variables para no desperdiciar una llamada de función virtual para buscar un campo simple de mi propia clase (y eso sucede cuando se accede a la propiedad).