Pregunta

¿Cuál es la diferencia entre las siguientes 2 formas de asignar e iniciar un objeto?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

y

self.aController= [[AController alloc] init];

La mayoría de los ejemplos de apple usan el primer método. ¿Por qué asignar, iniciar y objetar y luego liberar inmediatamente?

¿Fue útil?

Solución

Cada objeto tiene un recuento de referencia. Cuando va a 0, el objeto se desasigna.

Suponiendo que la propiedad se declaró como @property (conservar) :

Tu primer ejemplo, línea por línea:

  1. El objeto es creado por alloc , tiene un recuento de referencia de 1.
  2. El objeto se entrega al método self setAController: , que le envía un mensaje retener (porque el método no saber de dónde viene el objeto), incrementando su recuento de referencia a 2.
  3. El código de llamada ya no necesita el objeto en sí, por lo que llama a release , disminuyendo el recuento de referencias a 1.

Su segundo ejemplo básicamente hace los pasos 1 y 2 pero no 3, por lo que al final el recuento de referencia del objeto es 2.

La regla es que si crea un objeto, usted es responsable de liberarlo cuando haya terminado con él. En su ejemplo, el código se realiza con tempAController después de establecer la propiedad. Es responsabilidad del método de establecimiento llamar a retener si necesita ese objeto para quedarse.

Es importante recordar que self.property = foo; en Objective-C es realmente una abreviatura de [self setProperty: foo]; y que el El método setProperty: va a retener o copiar objetos según sea necesario.

Si la propiedad se declarara @property (copy) , entonces el objeto habría sido copiado en lugar de retenido. En el primer ejemplo, el objeto original sería lanzado de inmediato; en el segundo ejemplo, el recuento de referencia del objeto original sería 1 aunque debería ser 0. Por lo tanto, aún querría escribir su código de la misma manera.

Si la propiedad fue declarada @property (asignar) , self no reclama la propiedad del objeto, y alguien más debe retenerlo. En este caso, el primer ejemplo sería incorrecto. Este tipo de propiedades son raras, generalmente solo se usan para delegados de objetos.

Otros consejos

Como otros han notado, los dos fragmentos de código que muestra no son equivalentes (por razones de administración de memoria). En cuanto a por qué el primero es elegido sobre el segundo:

La formulación correcta de este último sería

self.aController= [[[AController alloc] init] autorelease];

En comparación con el primero, esto agrega una sobrecarga adicional a través del uso del grupo de liberación automática y, en algunas circunstancias, hará que la vida útil del objeto se extienda innecesariamente (hasta que se libere el grupo de liberación automática), lo que aumentará la huella de memoria de su aplicación.

El otro " posible " la implementación (dependiendo de dónde proviene el ejemplo) es simplemente:

aController = [[AController alloc] init];

Sin embargo, se desaconseja establecer una variable de instancia directamente en cualquier lugar que no sea un método init o dealloc. En otros lugares, siempre debe utilizar métodos de acceso.

Esto nos lleva a la implementación que se muestra en el código de muestra:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

Esto sigue las mejores prácticas desde:

  • Evita el autorelease;
  • Hace que la semántica de administración de memoria se borre de inmediato;
  • Utiliza un método de acceso para establecer la variable de instancia.

Tenga en cuenta también que su deseo de reducir el código a una sola línea es la razón por la que muchas personas usan Autorelease:

self.aController = [[[AController alloc] init] autorelease];

Aunque en teoría en el iPhone, la liberación automática es de alguna manera más costosa (nunca escuché una explicación clara de por qué) y, por lo tanto, es posible que desee liberarla explícitamente justo después de asignar el objeto en otro lugar.

Si está utilizando Xcode, puede ayudarlo a detectar dicho código con el analizador estático. Solo presiona Construir > > Construir y analizar

texto alternativo ??

Esto le mostrará un mensaje muy útil en dichos fragmentos de código.

alt text

Otra cosa a tener en cuenta es que su ejemplo depende de la definición @property de aController también.

Si se definió como @property (readwrite, retener) id aController; entonces su ejemplo funciona, mientras que si está definido como @property (readwrite, asignar) id aController; , entonces, la llamada adicional para liberar provocaría que su objeto fuera desasignado.

También puedes hacer

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

con una propiedad de retención, y funcionaría de la misma manera, pero es mejor usarlo de otra manera (para retener propiedades) porque es menos confuso, ese código hace que parezca que asigna un Controlador y luego se elimina de la memoria , cuando en realidad no lo hace porque setAController lo retiene.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top