2009-05-16 9 views
12

¿Cuál es la correcta? Este:Administración de la memoria y performSelectorInBackground:

NSArray* foo = [[NSArray alloc] initWithObjects:@"a", @"b", nil]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    ... 
    [foo release]; 
} 

O:

NSArray* foo = [[[NSArray alloc] initWithObjects:@"a", @"b", nil] autorelease]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    ... 
    [pool release]; 
} 

sé el primero funciona, pero Clang queja por él, así que me pregunto si hay un patrón mejor utilizar.

Me "sólo trato a cabo" la segunda, pero con autoreleasing, quién sabe si la ausencia de EXC_BAD_ACCESS significa que lo estás haciendo bien o que simplemente tuvo suerte ...

Respuesta

24

En primer lugar está mal .

performSelectorInBackground: withObject: conserva tanto la barra como el foo hasta que se realiza la tarea. Por lo tanto, debes liberar automáticamente a foo cuando lo crees y dejar performSelectorInBackground: withObject se ocupa del resto. Consulte documentation

Última es correcta porque suelta automáticamente a foo cuando lo crea. El grupo de creación que usted crea dentro de baz no tiene nada que ver con la corrección de la administración de la memoria de foo. Ese grupo de autorrelease es necesario para los objetos liberados automáticamente dentro de asignación y liberación de grupo en baz, no toca el conteo de retención de foo en absoluto.

+1

Oh, es justo ahí en la documentación! Tonto de mí. :) – lawrence

+4

Debo aclarar: DEBES crear y drenar un grupo de autorrelease dentro de -baz :, a menos que SABES que nada se enviará ni un método de restauración allí dentro. La mejor regla empírica es suponer que sucederá y crear/drenar un grupo de autorrelease, como en el ejemplo 2. Pero use [pool drain], no [pool release]. –

+0

Exactamente como dijo Jim Dovey: por lo general, necesita crear un grupo de liberación automática tal como lo hace para la función principal (consulte la Guía de programación de subprocesos). Es importante entender que este grupo no tiene nada que ver con la liberación automática de foo. –

2

El enfoque correcto ahora sería de hecho hacer:

NSArray* foo = [[[NSArray alloc] initWithObjects:@"a", @"b", nil] autorelease]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    @autoreleasepool { 
     ... 
    } 
} 
Cuestiones relacionadas