objective-c properties ivar

objective c - Razón para usar propiedades vs ivars en el objetivo c



objective-c properties (5)

En su ejemplo, @synthesize timesPlayed = _timesPlayed; crea un nuevo ivar llamado _timesPlayed y la propiedad se refiere a ese ivar. timesPlayed será una variable completamente separada sin relación alguna con la propiedad. Si solo usas @synthesize timesPlayed; entonces la propiedad se referirá a timesPlayed .

El propósito de la convención de subrayado es hacer que sea más fácil evitar la asignación accidental directamente a un ivar cuando desee hacerlo a través de la propiedad (es decir, a través del método del establecedor sintetizado). Sin embargo, todavía puede acceder a _timesPlayed directamente si realmente lo desea. Sintetizar una propiedad simplemente genera automáticamente un captador y configurador para el ivar.

En general, no necesita declarar un ivar para una propiedad, aunque puede haber casos especiales en los que desee hacerlo.

No he podido encontrar ninguna información sobre este tema y la mayor parte de lo que sé sobre él se produjo por completo accidente (y algunas horas de intentar averiguar por qué mi código no estaba funcionando). Mientras aprendía objetivo-c la mayoría de los tutoriales, he encontrado variables y propiedades con el mismo nombre. No entiendo el significado porque parece que la propiedad hace todo el trabajo y la variable se asienta allí. Por ejemplo:

Prueba.h

@interface Test : NSObject { int _timesPlayed, _highscore; } @property int timesPlayed, highscore; // Methods and stuff @end

Prueba.m

@implementation Test @synthesize timesPlayed = _timesPlayed; @synthesize highscore = _highscore; // methods and stuff @end

Lo que yo sé

1) Muy bien, hoy descubrí (después de horas de confusión) que no importa cuánto highscore = 5091231 a las propiedades de highscore = 5091231 más highscore = 5091231 , no cambiará nada cuando intentes llamar [prueba de highscore = 5091231 ] ya que seguirá devolviendo el valor de _highscore que (creo) es el ivar que se estableció en test.h. Por lo tanto, todo cambio de variables en test.m debe estar cambiando _puntuación más alta y no puntuación más alta. (Corrígeme si me equivoco aquí por favor)

2) Si lo comprendo correctamente (probablemente no), los ivars establecidos en test.h representan la memoria real, donde las propiedades @ son solo formas de acceder a esa memoria. Entonces, fuera de la implementación, no puedo acceder a la puntuación más alta sin pasar por la propiedad.

Lo que no entiendo

Básicamente, lo que no entiendo de esta situación es si debo o no usar los ivars o si puedo usar @property y @synthesize. Parece que los ivars son solo código extra que no hace nada pero me confunde. Algunos de los tuts más recientes que he visto no parecen usar ivars, pero algunos sí lo hacen. Entonces, ¿esto es solo una preferencia de codificación o es realmente importante? He intentado buscar en la documentación de Apple, pero me pierdo bastante allí y parece que nunca encuentro lo que estoy buscando. Cualquier guía será muy apreciada.


Esta puede ser una pregunta antigua ... pero en "tiempos modernos", @synthesize - NO es necesario.

@interface SomeClass : NSObject @property NSString * autoIvar; @end @implementation SomeClass - (id) init { return self = super.init ? _autoIvar = @"YAY!", self : nil; } @end

El _underscored respaldo ivar se sintetiza automáticamente ... y está disponible dentro de la implementación de ESTA clase, directamente (es decir, sin llamarse a self / llamando a los accesores generados automáticamente).

Solo necesita sintetizarlo si desea admitir la capacidad de la subclase para acceder al _backingIvar (sin llamarse a self ), o por miles de otras razones, que se describen en otro lugar .


Normalmente solo uso @property y @synthenize.

@property le da al compilador y al usuario instrucciones sobre cómo usar su propiedad. El clima tiene un setter, lo que es ese setter. Qué tipo de valor espera y devuelve. Estas instrucciones son utilizadas por el autocompletado (y finalmente el código que compilará contra la clase) y por el @synthesize

@synthesize creará por defecto una variable de instancia con el mismo nombre que su propiedad (esto puede ser confuso)

Normalmente hago lo siguiente

@synthesize propertyItem = _propertyItem;

esto creará de forma predeterminada un captador y un configurador, y manejará la liberación automática, así como la variable de instancia. La variable de instancia que utiliza es _propertyItem. Si desea acceder a la variable de instancia, puede usarla como tal.

_propertyItem = @"Blah";

esto es un error aunque Siempre debes usar el getter y setter. Esto permitirá que la aplicación se lance y se renueve según sea necesario.

self.propertyItem = @"Blah";

Esta es la mejor manera de manejarlo. Y la razón para usar la sección = _propertyItem de sintetizar es que no puede hacer lo siguiente.

propertyItem = @"Blah"; // this will not work.

le recomendará reemplazarlo con _propertyItem. pero deberías usar self.propertyItem en su lugar.

Espero que la información ayude.


Puede pensar en la sintaxis para sintetizar propiedades como @synthesize propertyName = variableName .

Esto significa que si escribes @synthesize highscore = _highscore; se creará un nuevo ivar con el nombre _highscore . Entonces, si lo desea, puede acceder a la variable en la que se almacena la propiedad directamente yendo a la variable _highscore .

Algunos antecedentes

Antes de alguna versión del compilador, no recuerdo que la declaración de síntesis no haya creado el ivar. En su lugar, solo decía qué variable debería usar, así que tenía que declarar tanto la variable como la propiedad. Si sintetizó con un prefijo de subrayado, entonces su variable necesitaba tener el mismo prefijo. Ahora ya no tiene que crear la variable, en su lugar se creará una variable con la variableName que especificó en la declaración de síntesis (si aún no lo ha declarado usted mismo, en cuyo caso solo se utiliza como la variable de respaldo). de la propiedad).

Lo que tu código está haciendo

Usted está creando explícitamente un ivar llamado highscore cuando declara la variable y luego crea implícitamente otro ivar llamado _highscore cuando sintetiza la propiedad. Estas no son la misma variable, por lo que cambiar una de ellas no cambia nada sobre la otra.

¿Deberías usar variables o no?

Esta es realmente una pregunta sobre la preferencia.

Variables pro

Algunas personas sienten que el código se vuelve más limpio si no tiene que escribir self. por todo el lugar. La gente también dice que es más rápido ya que no requiere una llamada de método (aunque probablemente nunca tendrá un efecto medible en el rendimiento de sus aplicaciones).

Propiedades pro

Cambiar el valor de la propiedad llamará a todos los métodos KVO necesarios para que otras clases puedan recibir notificaciones cuando el valor cambie. Por defecto, el acceso a las propiedades también es atómico (no se puede acceder a él desde más de un hilo), por lo que es más seguro leer y escribir desde múltiples hilos (esto no significa que el objeto al que apunta la propiedad sea seguro para los hilos, si es una matriz mutable, por lo que varios subprocesos aún pueden romper las cosas muy mal, solo evitará que dos subprocesos configuren la propiedad para cosas diferentes).


Puede usar @property y @synthesize sin declarar los ivars, como sugirió. El problema anterior es que su @synthesize asignó el nombre de la propiedad a un nuevo ivar generado por el compilador. Entonces, para todos los propósitos, la definición de su clase es ahora:

@interface Test : NSObject { int timesPlayed; int highscore; int _timesPlayed; int _highscore; } ... @end

Asignar un valor directamente a ivar timesPlayed nunca se mostrará si accede a él a través de self.timesPlayed ya que no modificó el ivar correcto.

Tienes varias opciones:

1 Elimina los dos ivars que declaraste en tu publicación original y simplemente deja que el dúo dinámico @property / @synthesize haga su trabajo.

2 Cambie sus dos ivars para ser prefijados por un guión bajo ''_''

3 Cambie sus declaraciones @synthesize para ser:

@implemenation Test @synthesize timesPlayed; @synthesize highscore; ...