views:

38

answers:

2

By delaying method calls inside a loop I noticed that the loop still runs, instead of waiting for the methods to complete. How can I get the loop to wait for the delayed methods to finish before continuing on to the next iteration?

I'm delaying the methods by using the three calls below,

for (int i = 0; i < [phrase length]; i++) {

//Do a bunch of stuff

[self performSelector:@selector(method1) withObject:nil afterDelay:0.1];
[self performSelector:@selector(method2) withObject:nil afterDelay:0.3];
[self performSelector:@selector(method3) withObject:nil afterDelay:0.6];

}
A: 

You shouldn't write code this way. You would effectively block the main UI thread while waiting for the selectors to fire. It's better to store the state of the loop in an instance variable and get the last-fired method (method3) to kick off the next iteration of the loop.

If you are not sure which method will complete first, you could also store a counter with the value 3 in the object that you decrement from the selectors, and when the counter reaches zero, perform the next iteration.

Marcelo Cantos
A: 

You need to break the loop up into a state machine, then exit/return back to the run loop in the middle of each fragment of the virtual for loop. That way you won't block the run loop and freeze the UI.

So the "for" loop open bracket can be done on one method, the middle in another method, and the closing bracket in yet another method (or one method that does all 3, depending on saved state and a switch statement). This can be done by saving the index variable (and any other needed local state) in instance variables. Then you can either use a timer to run each segment of the for loop method(s), or have your bunch-of-stuff-method123 send a notification or delegation back to start the next segment of the for loop.

To do this, it helps to know how a "for" loop is really built out of simpler "if" and "goto" statements.

hotpaw2