Ok, sono andato via e ho giocato con Xcode per un po ', ed ecco un modello di cosa sta succedendo, che sembra corrispondere a quello che sto vedendo.
Il blocco che ho usato in precedenza non sta facendo nulla di speciale, ma il codice di enumerateObjectsUsingBlock
sembra avere una propria NSAutoreleasePool
, in modo che sembra essere quello che stava causando dealloc
di essere chiamato su oggetti alloc'ed
, ma autoreleased all'interno del blocco.
Il seguente codice corrisponde a un comportamento quello che sto vedendo qui sopra:
#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;
}
Se rimuovo l'oggetto innerPool
, quindi il codice funziona come mi aspettavo in origine, e presumibilmente la piscina NSRunLoop
finirà per ripulire il vari oggetti NSString
.
NOTA: Questo thread è ora il risultato numero 2 Google per 'enumerateObjectsUsingBlock autorelease':
Google 'enumerateObjectsUsingBlock+autorelease'
Il primo risultato conferma questa risposta. Ringrazia tutti.
Wow, è bizzarro, non sono sicuro del perché non funzioni. – jtbandes
Ho visto persone eseguire un'autorelease '[[someVariable retain]] alla fine dei blocchi per restituire le cose, ma non sono sicuro del motivo per cui ciò dovrebbe fare la differenza se, come sospetto, venga eseguito un pool di autorelease. Non so però, è per questo che lo sto chiedendo, e ci sono tutti i tipi di articoli su come copiare i blocchi e passarli in giro, ma nulla che io possa trovare su qualcosa che dovrebbe essere semplice, come questo. –
Qual è l'errore/l'eccezione che ottieni? – nacho4d