Reputation: 348
I'm looking for a way to display strings at intervals in an NSTextField
while my application is idle. I know of one way to do this using sleep
although I don't think it's the best way to handle this. I'm thinking NSTimer
scheduledTimerWithTimeInterval
might be a good way to do it, but I'm not sure how to do it.
Here's my code:
- (void)showTextAtInterval {
NSTextField *textLabel;
[textLabel setStringValue:[NSString stringWithFormat:@"06/01/14"]];
sleep(5);
[textLabel setStringValue:[NSString stringWithFormat:@"Headlines"]];
....
}
EDIT: tried this, but only showed "Headlines" statically.
[self startTimer];
- (void)startTimer {
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(showTextAtInterval) userInfo:nil repeats:YES];
return;
}
- (void)showTextAtInterval {
NSTextField *textLabel;
[textLabel setStringValue:[NSString stringWithFormat:@"06/01/14"]];
[textLabel setStringValue:[NSString stringWithFormat:@"Headlines"]];
}
Upvotes: 0
Views: 167
Reputation: 53010
Your code has the right idea, just needs some changes.
First as you found out don't use sleep
- this stops the current thread completely and if you call it from your main thread, as you did, essentially your application.
There are a number of ways to do this. NSTimer
which you have picked is a good choice as you say you say only want to display the message(s) when your program is idle, NSTimer
has an invalidate
message you can use to stop the timer which you can call when your code is no longer idle.
UI updates must occur on the main thread and are not necessarily synchronous - on return from a method that updates the UI the UI may not yet reflect the change. This is why you only see "Headlines", you have two UI update calls on after the other and the second is done before you get to see the effect of the first.
What you need to do is: pause, show first message, pause, show second message, repeat as long as needed. So change your code so that on the first timer trigger you show the first message, the second time it triggers you show the second, etc. You can use an instance variable to keep track of which message should be displayed first. Better create an "idle message" class with methods to start and stop the messages and keep all the message selection and display logic within that class, your timer and other state should be instance variable of this class. Make sure all UI updates occur on the main thread, you can do that by ensuring the NSTimer
is scheduled on that thread (and put the logic to ensure that in the start method).
HTH
Upvotes: 1
Reputation: 27
Just to correct, I think you should add a private var and do a switch in showTextAtInterval
.
- (void)showTextAtInterval {
NSTextField *textLabel;
switch(iTimer)
{
case 0:
[textLabel setStringValue:[NSString stringWithFormat:@"06/01/14"]];
break;
case 1:
[textLabel setStringValue:[NSString stringWithFormat:@"Headlines"]];
break;
....
}
iTimer ++;
}
Upvotes: 0
Reputation: 19005
Initialize your timer
-(void)awakeFromNib{
[super awakeFromNib];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(showTextAtInterval) userInfo:nil repeats:YES];
}
And use your selector:
- (void)showTextAtInterval {
NSTextField *textLabel;
[textLabel setStringValue:[NSString stringWithFormat:@"06/01/14"]];
[textLabel setStringValue:[NSString stringWithFormat:@"Headlines"]];
....
}
Upvotes: 1