@zaph ha una buona soluzione. Ho pensato di provare da un'angolazione diversa. Poiché Objective-C è Obiettivo -C, perché non definire un qualche tipo di oggetto per eseguire questo ciclo temporizzato? Suggerimento: questo esiste. Possiamo usare NSTimer e la sua proprietà userInfo per risolvere questo problema. Penso che la soluzione sia una specie di elegante, se non un brutto scherzo.
// Somewhere in code.... to start the 'loop'
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
action:@selector(processNextTransaction:)
userInfo:@{
@"gains": [gainsArray mutableCopy]
}
repeats:NO];
// What handles each 'iteration' of your 'loop'
- (void)processNextTransaction:(NSTimer *)loopTimer {
NSMutableArray *gains = [loopTimer.userInfo objectForKey:@"gains"];
if(gains && gains.count > 0) {
id transaction = [gains firstObject];
[gains removeObjectAtIndex:0]; // NSMutableArray should really return the object we're removing, but it doesn't...
[self private_addTransactionToBankroll:transaction];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
action:@selector(processNextTransaction:)
userInfo:@{
@"gains": gains
}
repeats:NO];
}
}
Vorrei verificare che il NSTimer venga mantenuto aggiungendolo al ciclo di esecuzione. Se questo non è il caso, dovresti memorizzare un riferimento ad esso come una proprietà su qualunque classe stia gestendo tutto questo.
Vale anche la pena notare che poiché NSTimers viene installato sul loop principale per impostazione predefinita, non è necessario preoccuparsi di tutte le cose GCD. Poi di nuovo, se questo lavoro è un lavoro piuttosto difficile, potresti voler -processNextTransaction:
scaricare il suo lavoro su un'altra coda GCD e poi tornare alla coda principale per inizializzare l'istanza di NSTimer.
Assicurarsi di utilizzare il metodo -scheduledTimer...
; I metodi di classe timer...
su NSTimer
non lo installano su alcun ciclo e gli oggetti siedono semplicemente nello spazio senza fare nulla. Non fare lo repeats:YES
, sarebbe tragico, dato che avresti timer collegati al ciclo di esecuzione, volenti o nolenti, senza riferimenti che li indichino per sapere come o dove fermarli. Questa è generalmente una brutta cosa.
Per evitare le eccezioni EXC_BAD_ACCESS
, non deallocare mai l'oggetto il cui metodo è NSTimer
chiamare, se il timer non è ancora stato attivato. È possibile archiviare lo NSTimer
in sospeso in una proprietà della classe in modo da poter gestire questo tipo di cose. Se si tratta di un ViewController che sta gestendo tutto questo (che in genere è), quindi vorrei utilizzare il seguente codice per ripulire il timer su -viewWillDisappear
. (Questo presuppone che si sta impostando un nuovo timer per qualche @property
, self.timer
)
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if(self.timer) {
[self.timer invalidate]; // -invalidate removes it from the run loop.
self.timer = nil; // Stop pointing at it so ARC destroys it.
}
}
Utilizzando un 'NSTimer' è anche buona soluzione. – zaph
@zaph NSTimer non funziona bene con cocos2d o SpriteKit. Preferisci i metodi built-in 'schedule' forniti da CCNode e tutte le sue classi derivate. – YvesLeBorg