2012-04-26 17 views
45

¿Existe alguna diferencia entre utilizar el guión bajo y usar la palabra clave self en Objective-C cuando se llama a @property?Diferencia entre _ y uno mismo. en Objective-C

Declaración de la propiedad:

@property (weak, nonatomic) NSString *myString; 

Calling @synthesize en la propiedad:

@synthesize myString = _myString; 

¿Hay alguna diferencia si quiero usarlo en mi código? ¿Cuando? En el getter/setter?

self.myString = @"test"; 
_myString = @"test"; 
+0

'self' es un símbolo. '_' es un personaje en algunos símbolos. 'myString' y' _myString' son dos símbolos diferentes que están relacionados, no por la ortografía, sino porque están nombrados en el mismo '@ synthezize'. –

+0

Prueba la siguiente respuesta: http://stackoverflow.com/questions/5170631/what-does-synthesize-window-window-do – Peres

+2

@ Compruebe si la respuesta de Jonathan a esta pregunta anterior SO ayuda http: // stackoverflow .com/questions/5466496/why-rename-synthesized-properties-in-ios-with-leading-underscores – visakh7

Respuesta

68

self.myString = @"test"; es exactamente equivalente a escribir [self setMyString:@"test"];. Ambos están llamando a un método.

Podría haber escrito ese método usted mismo. Podría ser algo como esto:

- (void)setMyString:(NSString*)newString 
{ 
    _myString = newString; 
} 

Como se utilizó @synthesize, usted no tiene que molestarse en realidad escribir ese método, sólo puede permitir que el compilador para escribir por ti.

Por lo tanto, al mirar ese método, parece que llamar hará exactamente lo mismo que asignar un valor a la variable de instancia, ¿verdad? Bueno, no es tan simple.

En primer lugar, podría escribir su propio método setter. Si lo hace, se llamará a su método, y podría hacer todo tipo de cosas adicionales, así como establecer la variable. En ese caso, usar self.myString = llamaría a su método, pero al hacer _myString = no lo haría, y por lo tanto se utilizarían diferentes funcionalidades.

En segundo lugar, si alguna vez utiliza Key Value Observing, el compilador hace algunos trucos muy inteligentes. Detrás de escena, subclasifica tu clase y anula tu método setter (ya sea uno que escribiste tú mismo o uno generado por sintetizar), para hacer las llamadas al willChangeValueForKey: que se necesitan para que Key Value Observing funcione. No es necesario que sepa cómo funciona esto (¡aunque es bastante interesante si desea leer algo antes de acostarse!), Pero necesita saber que si desea que Key Value Observing funcione de manera automática, debe usar métodos setter.

En tercer lugar, llamar al método setter incluso si confía en sintetizar para escribir uno le da flexibilidad para el futuro. Es posible que desee hacer algo extra siempre que se modifique un valor, y en el momento en que descubra que desea hacerlo, puede escribir manualmente un método setter; si tiene la costumbre de usar siempre self.myString =, no lo hará ¡necesita cambiar el resto de su código para comenzar a llamar al nuevo método!

En cuarto lugar, lo mismo se aplica a las subclases. Si alguien más fuera a subclasificar tu código, si usas los setters entonces podrían anularlos para ajustar la funcionalidad.

Cada vez que accede directamente a la variable de instancia, explícitamente no proporciona una forma de que la funcionalidad adicional se enganche en ese punto. Dado que usted u otra persona podría querer conectar esa funcionalidad en el futuro, vale la pena utilizar los setters todo el tiempo, a menos que haya una buena razón para no hacerlo.

+0

Tenga en cuenta que no mencioné las implicaciones de administración de memoria. Si está utilizando ARC, son mucho menos relevantes en este caso, así que me salté sobre ellos. –

+0

Buena explicación :) – iTag

+0

Por cierto, con respecto a la primera oración ... Esto es cierto el 99% del tiempo, pero si tiene un formador personalizado (especificado con 'setter =' en la declaración de propiedad), entonces las dos formas no son exactamente equivalentes. –

8

estás en lo correcto - la primera versión (self.myString) llama al captador/definidor sintetizada y la segunda versión de acceso de la variable miembro privada directamente.

Parece que está utilizando ARC, por lo que en ese caso no hace mucha diferencia. Sin embargo, si no está utilizando ARC, puede hacer una diferencia, ya que la asignación directa al miembro privado no activará la lógica automática de retención/liberación o copia/liberación que se genera para usted utilizando synthesize.

+0

Son dos símbolos diferentes. Uno podría ser "aardvark" y el otro "zebra" y aún tener la relación variable-setter/getter. –

+0

@Hot Licks: tiene razón en que los nombres son irrelevantes, pero cuando leí la pregunta, creo que se preguntaba cuál era la diferencia práctica entre usar la propiedad sintetizada y simplemente usar la variable miembro que la respalda. –

+0

@EricPetroelje - sí, eso es exactamente lo que pregunté. ¡Gracias! – Kuba

3

El _ (guion bajo) es simplemente una convención, como se explica en this question.

Cuando no prefija un acceso a la propiedad con self., accede directamente a la variable subyacente, como en un c struct. En general, solo debe hacer esto en sus métodos init y en los accesores de propiedades personalizadas. Esto permite que cosas como las propiedades calculadas y KVC funcionen según lo previsto.

Cuestiones relacionadas