Ok, me fui y jugué un poco con Xcode, y aquí hay un modelo de lo que está sucediendo, que parece coincidir con lo que estoy viendo.
El bloque utilicé anterior no está haciendo nada especial, pero el código enumerateObjectsUsingBlock
parece tener su propia NSAutoreleasePool
, por lo que parece ser lo que estaba causando dealloc
para ser llamado en objetos alloc'ed
, pero autoreleased dentro del bloque.
El siguiente código coincide con el comportamiento en lo que estoy viendo arriba:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// simple block test - just iterate over some items and
// add them to a string
typedef void (^AccArrayBlock)(id obj, int idx, BOOL *stop);
// items to 'process'
NSArray *items = [NSArray arrayWithObjects:@"why ", @"must ", @"this ",nil];
int idx = 0;
BOOL doStop = NO;
// make sentence mutable, so we can assign it inside block
__block NSString *sentence = @"";
// make a similar block to what we'd pass to enumerate...
AccArrayBlock myBlock = ^(id obj, int idx, BOOL *stop)
{
// returns and assigns an autoreleased string object
sentence = [sentence stringByAppendingFormat:@"(%d) %@ ",idx,obj];
};
// enumerate items and call block
for (NSString *item in items) {
// create a pool to clean up any autoreleased objects in loop
// remove this line, and the sentence will be valid after loop
NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
myBlock(item, idx++, &doStop);
// drain the pool, autorelease objects from block
[innerPool drain];
if (doStop) {
break;
}
}
// faults if we drained the pool
// Program received signal: “EXC_BAD_ACCESS”.
NSLog(@"Sentence is %@",sentence);
[pool drain];
return 0;
}
Si quito el objeto innerPool
, a continuación, el código funciona como esperaba originalmente, y, presumiblemente, la piscina NSRunLoop
muy probable que limpiar el varios objetos NSString
.
NOTA: Este hilo es ahora el número 2 Google resultado para 'enumerateObjectsUsingBlock autorelease':
Google 'enumerateObjectsUsingBlock+autorelease'
El primer resultado confirma esta respuesta. Gracias a todos.
Guau, eso es extraño, no estoy seguro de por qué eso no funciona. – jtbandes
He visto a gente hacer una liberación automática '[[someVariable retain]] al final de bloques para devolver cosas, pero no estoy seguro de por qué eso debería marcar la diferencia si, como sospecho, se ejecuta un grupo de autorrelease. No sé, sin embargo, es por eso que pregunto, y hay todo tipo de artículos sobre cómo copiar bloques y pasarlos, pero no hay nada que pueda encontrar en algo que debería ser simple, como este. –
¿Cuál es el error/excepción que obtienes? – nacho4d