@zaph has a pretty good solution. I thought I would try from a different angle. Since Objective-C is Objective-C, why not define an object to execute this time loop? Hint: it exists. We can use NSTimer and its userInfo property to fix this. I think the solution is a kind of elegant, if not an unpleasant hack.
// 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]; } }
I would check that NSTimer is saved by adding a loop to the loop. If this is not the case, you should keep a reference to it as a property for any class that manages all this.
It's also worth noting that since NSTimers are installed by default in the main startup cycle, you donโt need to worry about all the GCD stuff. Again, if this work is quite complicated, you might want to -processNextTransaction: unload your work into another GCD queue, and then return to the main queue to initialize the NSTimer instance.
Be sure to use the -scheduledTimer... method ; timer... class methods on NSTimer do not set it to any loop, and objects just sit in space, doing nothing. Do not do repeats:YES , it would be tragic, because you would have timers attached to the run cycle perforce, without links pointing to them, to know how and where to stop them. This is usually bad.
To avoid EXC_BAD_ACCESS exceptions, never delete an object whose method NSTimer will be called if this timer is not already running. You might want to keep the pending NSTimer in a property of your class so that you can handle this. If it is a ViewController that manages all this (usually this), I would use the following code to clear the timer on -viewWillDisappear . (It is assumed that you set a new timer for some @property , self.timer )
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if(self.timer) { [self.timer invalidate];
source share