2010-09-27 19 views
15

Estoy tratando de comprender el propósito de la directiva synthesize con anulación de nombre de propiedad. Decir que tengo una interfaz definida de la siguiente manera:Objective-C sintetizar el nombre de propiedad anulando

@interface Dummy ... { 
    UILabel *_dummyLabel; 
} 

@property (retain, nonatomic) UILabel *dummyLabel; 

Y en el archivo de implementación, que tengo:

@synthesize dummyLabel = _dummyLabel; 

Por lo que entiendo, "dummyLabel" es sólo un alias de la variable de instancia " _dummyLabel ". ¿Hay alguna diferencia entre self._dummyLabel y self.dummyLabel?

Respuesta

24

Sí. self._dummyLabel no está definido, sin embargo, _dummyLabel no lo está.

La sintaxis de puntos se expande a las invocaciones de métodos simples, por lo que no es específico de las propiedades. Si tiene un método llamado -(id)someObject, por ejemplo en el caso de object.someObject, será como si hubiera escrito [object someObject];.

self.dummyLabel //works 
self._dummyLabel //does not work 
dummyLabel  //does not work 
_dummyLabel  //works 
[self dummyLabel]; //works 
[self _dummyLabel]; //does not work 
+0

Gracias por la respuesta rápida. Hm ... está bien, son [self.dummyLabel setText: @ "..."] y [_dummyLabel setText: @ "..."] haciendo lo mismo? Si es así, no veo ninguna gran ventaja de cambiar el nombre de _dummyLabel a dummyLabel. – Thomas

+0

@Thomas, lo tienes. –

+1

La ventaja de tener otro nombre para el ivar que para la propiedad es que puedes ver fácilmente en el código cuando estás accediendo a uno u otro. –

17

Su comprensión es incorrecta. dummyLabel es el nombre de la propiedad, y es no un alias para la variable de instancia - la variable de instancia es solo llamada _dummyLabel. Así se cumple lo siguiente para una instancia de Dummy llamada myObject:

  • [myObject dummyLabel] obras
  • myObject.dummyLabel obras
  • [myObject _dummyLabel] falla
  • myObject._dummyLabel falla
  • myObject->dummyLabel falla
  • myObject->_dummyLabel depende de la visibilidad de la ivar (@public, @private, @protected)
  • [myObject valueForKey: @"dummyLabel"] obras
  • [myObject valueForKey: @"_dummyLabel"] depende de la implementación de +accessInstanceVariablesDirectly (es decir, funcionará en el caso predeterminado donde +accessInstanceVariablesDirectly devuelve YES).
+0

Entonces, cuando quiero acceder a una variable de instancia dentro de un método, podría usar '_dummyLabel = @" blah "' - ¿y eso cambiaría el valor directamente, en lugar de pasar por un setter? Entonces, ¿podría tener una propiedad de solo lectura sin setter, pero aún así cambiarla internamente yendo directamente al ivar? Y si quiero usar un getter/setter dentro de un método de la clase, ¿usaría 'self.dummyLabel'? ¿O podría usar 'dummyLabel' directamente? –

0

no veo ninguna gran ventaja de cambiar el nombre de _dummyLabel a dummyLabel

En algunos ObjC tiempos de ejecución que tiene dificultades para llegar a las variables de instancia invisible para los usuarios de la clase. Para ellos, pegar un prefijo (o sufijo) en las variables de su instancia puede dejar en claro (o más claro) que no quiere que nadie se meta con sus variables. Sin embargo, no quieres esa basura en tus funciones públicas. Esto te permite quitártelo.

También podría ser útil si necesita mantener una interfaz antigua con un conjunto de nombres al mismo tiempo que un nuevo conjunto de API con un nuevo conjunto de nombres (setLastname vs. setSurname).

13

La ventaja de tener otro nombre para el Ivar que para la propiedad es que se puede ver fácilmente en el código cuando se está accediendo a una u otro - Andre K

I No puedo encontrar un botón de "comentario", así que tengo que publicar como una "respuesta".

Solo quería ampliar el comentario de Andre: saber cuándo está usando las propiedades sintetizadas frente a la variable de vanilla, sabe (especialmente en el caso de los ajustadores) cuando una variable se conserva/copia/libera automáticamente gracias a su agradable setter, vs manipulado a mano.

Por supuesto, si estás haciendo las cosas bien, ¡probablemente no necesites la ayuda de un colocador para retener/soltar objetos correctamente! Pero también puede haber otros escenarios donde hacer referencia a sus ivars como self.ivar en lugar de _ivar puede ser útil, como cuando está utilizando arregladores/captadores personalizados en lugar de los sintetizados por defecto. Quizás cada vez que modifique una propiedad, también desee almacenarla en NSUserDefaults. Así que es posible que tenga algo de código como esto:

@interface SOUserSettings : NSObject { 

BOOL _autoLoginOn; 

} 

@property (nonatomic, assign) BOOL autoLoginOn; 

@end 

@implementation SOUserSettings 

@synthesize autoLoginOn = _autoLoginOn; 

- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue { 

    _autoLoginOn = newAutoLoginOnValue; 
    [[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"]; 
} 

@end 

Nota: Esto es sólo ilustrativa de código, podría haber mil cosas mal con él!

Ahora, en su código, si tiene una línea que dice _autoLoginOn = YES, sabe que no se guardará en NSUserDefaults, mientras que si usa self.autoLoginOn = YES, sabrá exactamente qué va a pasar.

La diferencia entre _autoLoginOn y self.autoLoginOn es más que solo semántica.

+0

¡Excelente, que lo haya mencionado! ¡Hay una diferencia de verdad! –

0

Publicación anterior, pero creo que es importante mencionar que se recomienda acceder a variables mediante getters y setters (por lo tanto, con notación de puntos). Se recomienda encarecidamente acceder a un campo directamente (_ivar) solo al inicializarlo.

Hay algo de buen artículo de Apple: https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

último párrafo:

Siempre debería acceder a las variables de instancia directamente desde dentro de un método de inicialización porque en el momento de una propiedad se establece, el puede que el resto del objeto aún no se haya inicializado por completo. Incluso si no proporciona métodos de acceso personalizados o conoce los efectos secundarios del dentro de su propia clase, una futura subclase puede anular el comportamiento .

Cuestiones relacionadas