En Objective-C en iOS, ¿cuál es la diferencia (de estilo) entre “self.foo” y “foo” cuando se usan getters sintetizados?

He buscado muchas preguntas sobre los accesadores ObjC y los accesos sintetizados en vano. Esta pregunta es más una pregunta de “ayuda a resolver un problema”; No espero una respuesta, pero estoy buscando expertos para opinar sobre la discusión.

En una clase Cocoa Touch, escribiría un código como este (donde soundEffects es una propiedad de NSArray sintetizada):

 id foo = [self.soundEffects objectAtIndex:1]; 

Un colega me pidió que explicara por qué lo anterior es mejor que esta línea:

 id foo = [soundEffects objectAtIndex:1]; 

Bueno, funcionalmente, no es diferente.

Mis argumentos para el primero son los siguientes:

  1. self.soundEffects le dice a cada otro codificador que trabaja en el código que se trata de un iVar, no una variable de ámbito local.

  2. Si alguna vez lo necesitáramos, podríamos poner una lógica personalizada en el soundEffects .

  3. Sin ninguna razón concreta, “se siente” como lo correcto después de trabajar en Obj-C durante un año.

Acepta los argumentos # 1 y # 2 como válidos, pero también da el contrapunto:

  1. ¿No es esto solo bloat código?

  2. ¿No debería permitirse que una clase hable directamente con su propio iVars sin tener que llamar a un método (el getter) en sí mismo?

¿Ningún arrendatario?

Tu punto 1 no es del todo correcto: self.soundEffects no es un ivar, aunque puede darte algo que es , como lo hace en el caso de tu NSArray sintetizado, por el momento .

Esto a su vez implica que su punto 2 es el quid de la cuestión: si enruta todos los accesos a través del descriptor de acceso, todo estará muy bien encapsulado y podrá modificar la implementación más adelante sin tener que preocuparse por los efectos secundarios.

También es una buena práctica cuando usa el mutador, por lo que mantiene una gestión de memoria constante.

En su mayor parte, diría que es aconsejable enrutar a través de self.property para todo lo que es una propiedad, y restringir el acceso directo a las cosas que son estrictamente internas. Sin embargo, voy a admitir que en algunos casos, especialmente para las cosas que no usan la semántica de retain / copy , puede ser más una preferencia de estilo.

Personalmente me he decidido por usar un prefijo de subrayado para ivars, y este tipo de sintetizar

 @synthesize name = _name; 

De esa manera no los mezclo. El principal problema con no usar uno mismo es que este código

 _name = ... 

es muy diferente de

 self.name = ... 

Cuando @property usa la opción de retención. El primero no retiene el objeto, y el segundo llama al colocador sintetizado que conserva.

La única vez que hace una gran diferencia es con la asignación, por lo que tiendo a usar mi self. todo el tiempo, así que me aseguro de hacerlo en asignaciones.

el uso de algo como self.variable = nil hace que la variable pase por su setter y, por lo tanto, obtiene memoria administrada de forma gratuita. si solo usa variable = nil por ejemplo en un método dealloc, causará una fuga ya que en realidad no está pasando por el setter sintetizado para la variable y disminuyendo el conteo de retención. Ver esta publicación pérdida de memoria con uno mismo.

Por esta razón, es aconsejable (creo) usar siempre el yo. cuando se trata de variables de instancia que posee en lo que respecta a la administración de la memoria.

  self.soundEffects 

establece / obtiene la variable de instancia a través del setter / getter, y por lo tanto si queremos hacer algunas operaciones personalizadas cuando su valor cambia, esa lógica puede ir en su getter / setter.

También según ios 6, el ivar correspondiente a

  @property (no atómico) NSArray * propertyName; 

estarán

  _nombre de la propiedad 

así que supongo que no puedes usar

  id foo = [soundEffects objectAtIndex: 1]; 

más.No estoy seguro. En su lugar, debe usar

  id foo = soundEffects [1];