2011-05-19 18 views
6

Veo en algún código de muestra que se usa autorelease. No estoy familiarizado con las instancias cuando esto es obligatorio. Por ejemplo, si se crea un objeto de anotación¿Utilizar la liberación automática al establecer una propiedad de retención usando la sintaxis de punto?

Archivo de cabecera

@interface someViewController: UIViewController 
{ 
    Annotation *annotation; 
} 

@property (nonatomic, retain) Annotation *annotation; 

@end 

archivo de implementación

@implementation someViewController 
@synthesize annotation 
@end 

Pregunta: ¿Es el enfoque correcto si inicializar mi objeto de anotación en el archivo de aplicación como esta ?

self.annotation = [[Annotation alloc] initWithCoordinate:location]; 

¿Debo configurar la liberación automática para esto? ¿O puedo simplemente hacerlo de la manera normal y agregar la versión en el método dealloc?

+1

Posible duplicado de [Autorelease vs. release] (http://stackoverflow.com/questions/4077159/autorelease-vs-release) y hay muchas, muchas otras preguntas que responderán a esto si se toma el tiempo para leer ellos: [Buscar: iPhone retiene la propiedad de liberación automática] (http://stackoverflow.com/search?q=iphone+retain+property+autorelease) Esto: [Release/autorelease confusion] (http://stackoverflow.com/questions/ 1121343/release-autorelease-confusion-in-cocoa-for-iphone) es probablemente uno de los mejores. –

Respuesta

15

esto es correcto:

self.annotation = [[[Annotation alloc] initWithCoordinate:location] autorelease];

porque la propiedad de anotación se declara como una propiedad de retener, por lo que la asignación a la misma se incrementará su número de retener.

también necesitará, de todos modos, liberar self.annotation en -dealloc.

en resumen:

  1. init fijará retener recuento a 1;

  2. asignando a self.annotation, lo establecerá en 2;

  3. la liberación automática volverá a establecerlo en 1 cuando el ciclo principal se ejecute de nuevo;

  4. liberar en dealloc establecerá el conteo de retención en 0, por lo que el objeto será desasignado);

la mejor manera de pensar en autorelease es la siguiente, en mi opinión: autorelease se "programa" un "automático" release para el objeto en algún momento (casi) en el futuro (por lo general cuando el flujo de control va de vuelta al ciclo principal, pero los detalles están ocultos en las manos de Apple).

autorelease es sobre todo útil en conjunción con init, específicamente en los siguientes casos:

  1. cuando init una variable local, de modo que usted no tiene que release explícitamente antes de que salga del ámbito (el ciclo principal lo hará por usted);

  2. cuando regrese un puntero a un objeto que acaba de crear sin mantener la propiedad de la misma (caso típico de la create/make* tipo de selectores, se requiere que el receptor retain para conseguir la propiedad);

  3. con propiedades que retain, cuando se asigna a ellos un objeto que deben poseer de forma única;

  4. con estructuras de datos que se incrementan la cuenta de retención (NSMutableArray, NSMutableDictionary, etc.): por lo general debe autorelease una nueva init objeto ed cuando se agrega a dicha estructura de datos.

aparte del caso 2, es evidente que el uso de autorelease está destinado a mejorar la legibilidad del código y reducir la posibilidad de errores (lo que significa que en todos los demás casos, usted podría simplemente release explícitamente su objeto después de la asignación o al final del alcance).

al usar propiedades, siempre debe verificar si son del caso retain o assign/copy; en el primer caso, la asignación de un nuevo objeto ed init a una propiedad generalmente requiere autorelease.

De todos modos, sugeriría al menos rozar uno de los muchos tutoriales en memory management for iOS.

+0

Una manera rápida, si escribe 'annotation = [[Annotation alloc] initWithCoordinate: location];' sin el 'self' el conteo de retención no aumentará. – dombesz

2

Autorelease indica al objeto que se libere antes de abandonar el ámbito.

A veces, cuando el código, te vas a encontrar algo como esto

- (void)doSomething 
{ 
    if(true) 
    { 
     NSString *foo = [[NSString alloc] initWithString:@"foo"]; 

     //Some execution here 

     [foo release]; 
    } 
} 

- (void)doSomething 
{ 
    if(true) 
    { 
     //By doing this is telling to to release foo object before getting out of the scope 
     //which is similar with above practice 
     NSString *foo = [[[NSString alloc] initWithString:@"foo"] autorelease]; 

     //Or you can do it this way 
     NSString *foo = [[NSString alloc] initWithString:@"foo"]; 
     [foo autorelease]; 

     //Some execution carry on, it'll release foo before entering next scope 

    } 

// esto está fuera del alcance }

Por supuesto, la liberación de un objeto no significa cancelar la asignación del objeto . A veces se conserva el objeto por lo que aún puede usarlo fuera de su alcance.

A juzgar por su pregunta, si su objeto se encuentra dentro de su archivo de cabecera/interfaz. Debe liberarlo en el método dealloc. CMIIW.

+0

solo para aclarar, mi entendimiento es que incluso si el objeto está en el archivo de encabezado, aún podríamos necesitar ejecutar la liberación automática si, por ejemplo, ocurre self.annotation = [[Annotation alloc] init .... ¿Es eso correcto? – Zhen

+0

@Zhen generalmente inicializará su objeto de interfaz (incluso haciéndolo nulo). Por lo tanto, liberar en dealloc es imprescindible. Pero si, por casualidad, inicia su objeto nuevamente (lo que provocará la pérdida de memoria porque perdió su dirección de memoria anterior), sí, puede configurar la liberación automática. Recuerda cuando alloc e init, estamos hablando de la dirección de la memoria. Esto es lo que sé, puede leer/preguntar al programador experimentado si desea obtener más información. – sayzlim

Cuestiones relacionadas