0

I'm working on a very simple iPhone game that involves choosing the right colored button as many times in a row based on a randomized voice prompt. I have it set up so that if the button is one color and gets clicked, it always goes to a hard-coded color every time (e.g. if you click red, it always turns blue). The color change method is set up in an IBOutlet. I have a timer set up in a while loop, and when the timer ends it checks if the player made the right selection. The problem is that the button color change does not occur until after the timer runs out, and this causes a problem with the method used to check the correct answer. Is there a way to make this color change happen instantly? From what I've searched I know it has something to do with storyboard actions not occurring until after code executes, but I haven't found anything with using a timer. Here is a section of the method that calls the timer if the answer is correct:

BOOL rightChoice = true;
int colorNum;
NSDate *startTime;
NSTimeInterval elapsed;
colorNum = [self randomizeNum:middle];
[self setTextLabel:colorNum];
while (rightChoice){
    elapsed = 0.0;
    startTime = [NSDate date];
    while (elapsed < 2.0){
        elapsed = [startTime timeIntervalSinceNow] * -1.0;
        NSLog(@"elapsed time%f", elapsed);
    }
    rightChoice = [self correctChoice:middleStatus :colorNum];
    colorNum = [self randomizeNum:middle];
}
Mutix
  • 4,196
  • 1
  • 27
  • 39
erasmuss22
  • 105
  • 1
  • 12

1 Answers1

2

One of two things stood out

  • You're using a while loop as a timer, don't do this - the operation is synchronous.
  • If this is run on the main thread, and you code doesn't return, your UI will update. The mantra goes: 'when you're not returning you're blocking.'
  • Cocoa has NSTimer which runs asynchronously - it is ideal here.

So let's get to grips with NSTimer (alternatively you can use GCD and save a queue to an ivar, but NSTimer seems the right way to go).

Make an ivar called timer_:

// Top of the .m file or in the .h
@interface ViewController () {
  NSTimer *timer_;
}
@end

Make some start and stop functions. How you call these is up to you.

- (void)startTimer {
  // If there's an existing timer, let's cancel it
  if (timer_)
    [timer_ invalidate];

  // Start the timer
  timer_ = [NSTimer scheduledTimerWithTimeInterval:5.0
                                            target:self
                                          selector:@selector(onTimerFinish:)
                                          userInfo:nil
                                           repeats:NO];
}

- (void)onTimerFinish:(id)sender {
  NSLog(@"Timer finished!");

  // Clean up the timer
  [timer_ invalidate];
  timer_ = nil;
}

- (void)stopTimer {
  if (!timer_)
    return;

  // Clean up the timer
  [timer_ invalidate];
  timer_ = nil;
}

And now

  • Put your timer test code in the onTimerFinish function.
  • Make an ivar that stores the current choice. Update this ivar when a choice is made and make the relevant changes to the UI. Call stopTimer if the stop condition is met.
  • In the onTimerFinished you can conditionally call and startTimer again if you desire.

Hope this helps!

Community
  • 1
  • 1
Matt Melton
  • 2,493
  • 19
  • 25
  • 1
    Wow that worked perfectly! Thank you so much! I have an account that I use frequently at work, but the password is there, so I don't have enough rep to give an upvote. Otherwise you definitely deserve one! – erasmuss22 Apr 26 '12 at 15:22