This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Change the time interval of a Timer
So I have a timer:
timer=[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(createNewImage) userInfo:nil repeats:YES];
And I would like that the timer decrease every ten seconds, that scheduledTimerWithTimeInterval goes to 1.5 after ten seconds then to 1.0 after 10 seconds... Is it possible to do this, and if it is possible, how can I do it?
You can't modify a timer after you created it. To change the timer interval, invalidate the old timer and create a new one with the new interval.
You don't have to use several timers, all you have to do is add a variable to use for the time interval, then create a method that invalidates the timer, changes the variable and starts the timer again. For instance you could make a method that starts the timer.
int iTimerInterval = 2;
-(void) mTimerStart {
timer = [NSTimer scheduledTimerWithTimeInterval:iTimerInterval target:self selector:#selector(createNewImage) userInfo:nil repeats:YES];
}
-(void) mTimerStop {
[timer invalidate];
iTimerInterval = iTimerInterval + 5;
[self mTimerStart];
}
This would be the simple way to decrease the timer interval and keep the timer going, but I would personally prefer using the one below, because it makes sure that the timer has only ran once, that way it will not duplicate the instance, forcing your app to become glitchy and it also makes things easier for you.
int iTimerInterval = 2;
int iTimerIncrementAmount = 5;
int iTimerCount;
int iTimerChange = 10; //Variable to change the timer after the amount of time
bool bTimerRunning = FALSE;
-(void) mTimerToggle:(BOOL)bTimerShouldRun {
if (bTimerShouldRun == TRUE) {
if (bTimerRunning == FALSE) {
timer = [NSTimer scheduledTimerWithTimeInterval:iTimerInterval target:self selector:#selector(mCreateNewImage) userInfo:nil repeats:YES];
bTimerRunning = TRUE;
}
} else if (bTimerShouldRun == FALSE) {
if (bTimerRunning == TRUE) {
[timer invalidate];
bTimerRunning = FALSE;
}
}
}
-(void) mCreateNewImage {
//Your Code Goes Here
if (iTimerCount % iTimerChange == 0) { //10 Second Increments
iTimerInterval = iTimerInterval + iTimerIncrementAmount; //Increments by Variable's amount
[self mTimerToggle:FALSE]; //Stops Timer
[self mTimerToggle:TRUE]; //Starts Timer
}
iTimerCount ++;
}
-(void) mYourMethodThatStartsTimer {
[self mTimerToggle:TRUE];
}
I didn't finish all of the coding, but this is most of what you will need. Just change a few things and you'll be good to go!
You will need a set or sequence of timers, one for each different time interval. Stop/invalidate one timer and start the next timer when you want to change to the next time interval in your time sequence.
Related
I want to invoke a method 24 times but between each invocation I want an interval of 1 sec,
now am using
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(loadNumber) userInfo:nil repeats:YES];
but how to count invocations, I want to invalidate timer after 24 count can I invalidate that.
Create an instance variable for an int, it doesn't matter what you call it. Set it to "0" before you call the timer.
someInt = 0;
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(loadNumber:) userInfo:nil repeats:YES];
In the action that the time calls check the value of this number to make sure the action should be performed and increment the number.
- (void)loadNumber:(NSTimer *)sender
{
if (someInt <= 24) {
//do something
someInt ++;
}else{
[sender invalidate];
someInt = 0;
}
}
You should set up a counter in loadNumber, which will invalidate your NSTimer after your desired repeat counts.
I am trying to use the current time in my movie player to increment a sliders value in my iPad app.
slider.maximumValue=10;
slider.minimumValue=0;
How can I increment slider.value from 0 to 10 in a specific time period?
You can use an NSTimer to repeatedly add 1 to your slider value if you know the specific time period beforehand:
NSTimer *aTimer = [NSTimer scheduledTimerWithTimeInterval:(timePeriod/slider.maximumValue)
target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
- (void)timerFired:(NSTimer*)theTimer {
[slider setValue:slider.value + 1.0];
if(slider.value == slider.maximumValue) {
[theTimer invalidate];
}
}
I have a -(void) method being executed and at one point it gets to a while loop that gets values from the accelerometer directly the moment it asks for them
I went throughout the documentation regarding the NSTimer class but I couldn't make sense of how exactly I am to use this object in my case :
e.g.
-(void) play
{
......
...
if(accelerationOnYaxis >0 && accelerationOnYaxis < 0.9 )
{
startTimer;
}
while(accelerationOnYaxis >0 && accelerationOnYaxis < 0.9)
{
if(checkTimer >= 300msec)
{
printOut_AccelerationStayedBetweenThoseTwoValuesForAtLeast300msecs;
break_Out_Of_This_Loop;
}
}
stopTimerAndReSetTimerToZero;
.....
more code...
....
...
}
Any help?
You cannot do it with NSTimer, because it needs your code to exit in order to fire. NSTimer uses the event loop to decide when to call you back; if your program holds the control in its while loop, there is no way for the timer to fire, because the code that checks if it's time to fire or not is never reached.
On top of that, staying in a busy loop for nearly a second and a half is going to deplete your battery. If you simply need to wait for 1.4s, you are better off calling sleepForTimeInterval:, like this:
[NSThread sleepForTimeInterval:1.4];
You can also use clock() from <time.h> to measure short time intervals, like this:
clock_t start = clock();
clock_t end = start + (3*CLOCKS_PER_SEC)/10; // 300 ms == 3/10 s
while(accelerationOnYaxis >0 && accelerationOnYaxis < 0.9)
{
if(clock() >= end)
{
printOut_AccelerationStayedBetweenThoseTwoValuesForAtLeast300msecs;
break_Out_Of_This_Loop;
}
}
NSTimer works a little different than you want. What you need is a counter for your timer, to get how many times it looped. If your counter gets on 14 (if it's an integer), you can invalidate it.
//start timer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(play:)
userInfo:nil
repeats:YES];
//stop timer
[timer invalidate];
You can create your function without that while.
- (void)play {
......
...
counter++; //declare it in your header
if(counter < 14){
x++; //your integer needs to be declared in your header to keep it's value
} else {
[timer invalidate];
}
useValueofX;
}
Take a look at the documentation.
I'm struggling with this. I saw some code where you can do this :
- (void)startTimer {
pauseTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(doActions) userInfo:nil repeats:YES];
}
Then call it in doActions.
Problem is i want to call it while a button is being pressed, and do actions is an IBaction. I keep getting a sigAbrt.
Can someone give me some sample code where you cay change a label from 'on' to 'off' every 1 second while a button is being pressed?
EDIT
i mean if doActions looks like this
- (IBAction) doActions {
for(int j; j<100; j++){
theLabel.hidden != theLabel.hidden;
//Does invalidate timer go here?
}
}
It still isn't clear to me, what you're trying to accomplish: I would have found it much easier, if you simply had it written down in plain english, after all.
That said, here's what I think will get you where you want to go:
// Assuming ivars:
// NSTimer* toggleTimer
// NSUInteger toggleCount
- (void)toggleTimerFired:(NSTimer*)timer
{
if ( toggleCount++ >= 100 ) {
[self stopToggling:self];
return;
}
// do whatever you need to do a hundred times here
}
- (IBAction)stopToggling:(id)sender
{
[toggleTimer invalidate], toggleTimer = nil; // you don't want dangling pointers...
// perform any other needed house-keeping here
}
- (IBAction)startToggling:(id)sender
{
[self stopToggling:self]; // if `startToggling:` will NEVER be called when a timer exists, this line CAN be omitted.
toggleCount = 0;
toggleTimer = [NSTimer scheduledTimerWithTimeInterval:1. target:self selector:#selector(toggleTimerFired:) userInfo:nil repeats:YES];
}
Depending on what exactly you want to do, startToggling: needs to be sent on either touchUpInside or touchDown. In the second case, stopToggling: probably needs to be called on any touchUp... event of the button.
- (void)startTimer {
pauseTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(doActions) userInfo:nil repeats:YES];
}
- (void) doActions {
theLabel.hidden != theLabel.hidden;
}
I have a countdown timer in my game and I'm trying to figure out how to make it so that it shows two decimal places and records with 2 decimal places in my table. Right now it counts down as a whole number and records as a whole number. Any ideas?
-(void)updateTimerLabel{
if(appDelegate.gameStateRunning == YES){
if(gameVarLevel==1){
timeSeconds = 100;
AllowResetTimer = NO;
}
timeSeconds--;
timerLabel.text=[NSString stringWithFormat:#"Time: %d", timeSeconds];
}
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimerLabel) userInfo:nil repeats:YES];
To have sub-second updates, the timer's interval needs to be < 1. But the precision of NSTimer is just around 50 ms, so scheduledTimerWithTimeInterval:0.01 will not work.
Moreover, the timer can be delayed by various activities, so using timeSeconds will lead to inaccurate timing. The usual way is compare the NSDate now with the date when the timer starts. However, as this code is for a game, the current approach may cause less frustration to players esp. if the program or background processes consumes lots of resources.
The first thing to do is to convert the countdownTimer to sub-second interval.
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:0.67 target:self selector:#selector(updateTimerLabel) userInfo:nil repeats:YES];
Then, don't count down the time by seconds, but centiseconds:
if(appDelegate.gameStateRunning == YES){
if(gameVarLevel==1){
timeCentiseconds = 10000;
AllowResetTimer = NO;
}
}
timeCentiseconds -= 67;
Finally, divide by 100 in the output:
timerLabel.text=[NSString stringWithFormat:#"Time: %d.%02d", timeCentiseconds/100, timeCentiseconds%100];
Alternatively, use a double:
double timeSeconds;
...
if(appDelegate.gameStateRunning == YES){
if(gameVarLevel==1){
timeSeconds = 100;
AllowResetTimer = NO;
}
}
timeSeconds -= 0.67;
timerLabel.text=[NSString stringWithFormat:#"Time: %.2g", timeSeconds];