Thanks very much for this detailed explanation. I realize my mistake now; I was thinking about this in the wrong way. I eventually coded it as follows:

- (IBAction)startTimer:(id)sender
{ timeInSeconds = [((NSNumber *)[inTextField objectValue]) intValue];
   [NSTimer scheduledTimerWithTimeInterval:1.0
                                    target:self
                                  selector:@selector(checkTimer:)
                                  userInfo:nil
                                   repeats:YES];
}


- (void)checkTimer:(NSTimer *)timer
{
   if (timeInSeconds == 0) {
       [timer invalidate];
       [outTextField setStringValue:@"Finished timing"];
   } else {
[outTextField setStringValue:[NSString stringWithFormat:@"%d more second(s) to go", timeInSeconds]];
       NSLog(@"in loop, timeInSeconds is %d", timeInSeconds);
       timeInSeconds--;
   }
}

Thanks again to all.
Daniel


Ken Thomases wrote:
On Jun 27, 2008, at 10:55 PM, Daniel Richman wrote:

I'm trying to program a simple timer app: you enter a number of seconds, and it updates a text field every second with the number of secs remaining. The problem is that I'm not able to do anything with the UI while this is going on. Here's my code:

- (IBAction)startTimer:(id)sender
{
  [startButton setState:NSOffState];
int timeInSeconds = [((NSNumber *)[inTextField objectValue]) intValue];
    while (timeInSeconds > 0) {
[outTextField setStringValue:[NSString stringWithFormat:@"%d more second(s) to go", timeInSeconds]];
            sleep(1);
      timeInSeconds--;
  }
    [outTextField setStringValue:@"Finished timing"];
  NSBeep();
}

What's happening is that if I enter a number and then press 'start', 'start' stays in the 'pressed' position until the loop finishes, after which it returns to the normal position. My guess is that this is stopping any other UI events from occurring. This would also explain why I'm able to log a message each time the loop iterates.

But I'm still not sure why the button is staying pressed. Thoughts, anyone?

What others have said is correct, but I wanted to provide some more explanation.

Let's think about why the button is staying pressed. I'll illustrate purely using pseudocode. I'm _not_ implying that this is literally what's happening, but let's imagine that your button click is processed by code which looks something like this:

while (get an event)
{
    if (event is a mouse click on a button)
    {
        paint the button as pressed
invoke the button's action method on the button's target // this calls your startTimer: method
        paint the button as normal
    }
    else /* ... */
}

Now, can you see why the button is staying pressed? The invocation of your startTimer: method is not exiting until N seconds go by, and the button doesn't get repainted until after it does. The code in the framework isn't magical or special. Just like code that you write, it has to finish with one thing before it can go on to the next thing. In your code, you wouldn't expect the [outTextField setStringValue:@"Finished timing"] to be performed before the while loop exits. Why would you expect anything else to?

Next, let's image we insert some code into the while loop, at the end of the block:

while (get an event)
{
    if (event is a mouse click on a button)
    /* ... same as above ... */

    for each window
    {
for each view in this window which needs to be redrawn due to a state change
            draw this view
    }
}

This window and view redrawing code is what is responsible for showing the changes you make to the output text field. So, by blocking inside startTimer: you're not only preventing the button from being redrawn, you're also preventing the output text field from being redrawn with its new content.


That's the explanation behind what the others have told you. Unless and until your method returns, none of the other work that's waiting to be done will get done.

I hope that helps.

Cheers,
Ken
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to