Diferencia entre _ y yo. en Objective-C

¿Hay alguna diferencia entre usar el guión bajo y usar la palabra clave self en Objective-C cuando se llama a @property ?

Declaración de propiedad:

 @property (weak, nonatomic) NSString *myString; 

Llamando a @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"; 

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

Podrías haber escrito ese método tú mismo. Puede parecerse a esto:

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

Como @synthesize , no tienes que molestarte en escribir ese método, solo puedes permitir que el comstackdor lo escriba por ti.

Entonces, al mirar ese método, parece que llamarlo 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 hacer _myString = no lo haría, y por lo tanto, se usaría una funcionalidad diferente.

En segundo lugar, si alguna vez utiliza Key Value Observing, el comstackdor 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 a 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 adicional siempre que se cambie 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 = , entonces usted ¡no necesitará cambiar el rest 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 extra 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.

Está en lo cierto: la primera versión ( self.myString ) llama al getter / setter sintetizado y la segunda versión accede directamente a la variable de miembro privada.

Parece que estás usando ARC, entonces 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 desencadenará la lógica automática de retención / liberación o copia / liberación que se genera para usted mediante el uso de synthesize .

El _ (guión bajo) es simplemente una convención, como se explica en esta pregunta .

Cuando no prefija un acceso de propiedad consigo self. , está accediendo directamente a la variable subyacente, como en ac 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.

Hay un consejo que no se menciona, el acceso con guion bajo es más rápido y el acceso usando el yo es más seguro (KVC). Tal vez esto puede resumir cuando tienes que usar cada uno.