Re: while loop with sleep(): logging works, but not UI events
Re: while loop with sleep(): logging works, but not UI events
- Subject: Re: while loop with sleep(): logging works, but not UI events
- From: Daniel Richman <email@hidden>
- Date: Sat, 28 Jun 2008 08:13:00 -0700
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 (email@hidden)
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:
This email sent to email@hidden