Goal C to Delay Cycle

I have a for loop that I want to add a delay between iterations. I changed waitUntilDone to YES and got the same results. My array has only two numbers, and both are called after five seconds instead:

0s - nothing 5s - The block is called 10s-Block, called

for(NSNumber* transaction in gainsArray) { double delayInSeconds = 5.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { NSLog(@"Block"); [self performSelectorOnMainThread:@selector(private_addTransactionToBankroll:) withObject:transaction waitUntilDone:NO]; }); } 2015-06-16 20:11:06.485 TestApp[97027:6251126] Block 2015-06-16 20:11:06.485 TestApp[97027:6251127] Block 

I use Cocos2d if that matters

+5
source share
2 answers

The for loop will send one after the other so that they essentially linger at the same time.
Instead, set an incremental delay for each other:

 double delayInSeconds = 0.0; for(NSNumber* transaction in gainsArray) { delayInSeconds += 5.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { NSLog(@"Block"); [self performSelectorOnMainThread:@selector(private_addTransactionToBankroll:) withObject:transaction waitUntilDone:NO]; }); } 
+4
source

@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]; // -invalidate removes it from the run loop. self.timer = nil; // Stop pointing at it so ARC destroys it. } } 
+1
source

All Articles