I created a timer, and was wondering if it is at all possible to make the timer go slower when it reaches a certain second: 1..2..3..4..4.1..4.2.
For example, the timer is increasing by 1 second, then at 4 seconds, the time slows down showing milliseconds.
if(i = 4) {
}
It depends on what you want.
Of course, you can't slow down the time, but you can simulate it.
For example, you check how much time has already passed. If it is 1, 2, 3 seconds, you NSLog 1, 2, 3. Then when 4 seconds has passed, you start logging milliseconds.
E.g.
if (i < 4) {
NSLog(#"%d", i);
} else {
NSLog(#"4.%d", i - 4);
}
Sure, logging can be substituted with whatever you need.
P.S. The answer is in Objective-C, but that changes nothing.
You can use a solution like this:
Declare a float to register your time and a NSTimer to perform the action.
#property NSTimer *timer;
#property float time;
Call startTimer to start the actions.
- (void) startTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(secondsAction)
userInfo:nil
repeats:YES];
}
- (void) secondsAction {
self.time += 1;
NSLog(#"%d", (int)self.time);
if(self.time == 4) {
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(milisecondsAction)
userInfo:nil
repeats:YES];
}
}
- (void) milisecondsAction {
self.time += 0.1;
NSLog(#"%.1f", self.time);
}
Related
A strange situation:
If I started my Timer again and again without stopping it first, it will count increasingly fast. I guess it is because it starts multiple timers now?
However, when I finally want to stop it, it cannot be stopped...keep going forever.
(Maybe for design consideration, I should disable users from pressing start again, but I'm wondering what is really behind this and why the timer can't be stopped.)
- (IBAction)Start:(id)sender {
countInt = 0;
self.Time.text = [NSString stringWithFormat:#"%i", countInt];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countTimer) userInfo:nil repeats:YES];
}
- (IBAction)Stop:(id)sender {
[timer invalidate];
}
- (void) countTimer {
countInt += 1;
self.Time.text = [NSString stringWithFormat:#"%i", countInt];
}
#end
The simple solution is to call stop at the beginning of the start method.
Note that in stop you should also set timer = nil;
Assuming there is a property timer
#property NSTimer *timer;
the most reliable way to start and stop the timer only once respectively is to create two methods.
- (void)startTimer
{
if (self.timer == nil) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countTimer)
userInfo:nil
repeats:YES];
}
}
- (void)stopTimer
{
if (self.timer != nil) {
[self.timer invalidate];
self.timer = nil;
}
}
Both methods perform a check, so the timer can't be restarted while it's running and vice versa.
Now just call the methods in the start/stop IBActions (the names should start with a lowercase letter).
- (IBAction)Start:(id)sender {
countInt = 0;
self.Time.text = [NSString stringWithFormat:#"%i", countInt];
[self startTimer];
}
- (IBAction)Stop:(id)sender {
[self stopTimer];
}
The benefit is pressing Start has no effect when the timer is already running.
When you hit 'start' multiple times you are creating multiple timers. So you are getting multiple timers firing and executing your timer callback. In this timer callback you increment counters. Since there are many timers now, they are all incrementing your counter, hence explaining your rapid increase in the counter.
You can allow the user to tap Start twice, as long you can define what happens when you hit Start while the timer is already going. But you definitely need to invalidate the old timer before creating a new one.
- (IBAction)Start:(id)sender {
...
// Stop previous timer before creating a new timer.
if (timer != nil) {
[timer invalidate]
}
...
}
I'm using NSTimer to display seconds on a label while recording.
I'm starting the timer when the record button is tapped and stopping it when the stop button is tapped.
When I tap the play button the timer is not restarting.
-(void)startTimer
{
playTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(timerController)
userInfo:nil
repeats:YES];
}
- (NSString*)getTimeStr : (int) secondsElapsed
{
seconds = secondsElapsed % 60;
int minutes = secondsElapsed / 60;
int hours = secondsElapsed/3600;
return [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
}
- (void)timerController{
seconds++;
[[self timeLabel] setText:[self getTimeStr:(seconds)]];
}
- (IBAction)recordTapped:(id)sender {
[self startTimer];
}
- (IBAction)stopTapped:(id)sender {
[playTimer invalidate];
playTimer=nil;
_timeLabel.text=#"00:00:00";
}
- (IBAction)playTapped:(id)sender {
[self startTimer];
}
As mentioned in the comments, there are two bugs around:
Bug #1
You should always reset the variable seconds to 0 before restarting the timer (probably reset it at the 1st line of startTimer)
Bug #2
The variable seconds is overwritten by the 1st line of getTimeStr function. You should replace seconds with int sec and for the return line, replace seconds with sec.
- (void)resetTimer {
if(playTimer) {
[playTimer invalidate];
playTimer = nil;
}
}
You should call resetTimer method every time before startTimer again.
I make one 30:00 min countdown timer, now when I load next page and back on first page my timer is on but label which show time it's stopped.
Any idea for that when I come on first page and my timer is on and start at same point, in short I need run my timer in background.
This is the code which I use in same view controller where the timer is, but it's not working.
- (void)viewWillDisappear:(BOOL)animated
{
[Timecount invalidate];
}
-(void)viewDidAppear:(BOOL)animated
{
// [self countdownTimer];
}
-(void)viewWillAppear:(BOOL)animated
{
[self countdownTimer];
}
-(void)countdownTimer
{
secondsLeft = hours = minutes = seconds = 0;
if([Timecount isValid])
{
}
Timecount = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
}
Im making an iphone game that uses NStimer for movement. I found out that there is a bug that makes the timers stack some times, but i havnt found out what causes is. Is there any way to see how many timers are allocated and is there any way to prevent it by doing something like this:
If(myTimer.numberOfAllocatedTimers == 0) {
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateme) userInfo:nil repeats:YES];
}
Try this:
// use this to start timer
myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(doSthing) userInfo:nil repeats:YES];
// use this to stop timer
if (myTimer) {
[myTimer invalidate];
myTimer = nil;
}
A little more context on where this code is being used would be helpful.
However, I'll try to explain why it's happening anyway.
Every time you use [NSTimer scheduledTimerWithTimeInterval...], a new timer is created, and will start repeating. If your code creates a timer inside the callback method, see example below, you'll stack timers.
- (void)updateme {
if ([NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateme) userInfo:nil repeats:YES]) {
// This creates stacked timers!
}
}
Here's how you should do it:
#property (nonatomic, strong) NSTimer *myTimer;
...
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateme:) userInfo:nil repeats:YES];
...
- (void)updateme:(NSTimer *)timer {
if (timer == self.myTimer) {
// Do something because the timers are equal
}
}
I have a void function which just have NSLog(#"Call me"); in its body.
I call it in my view in every ten seconds by using
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(yourMethod) userInfo:nil repeats:YES];
But I want it to stop it after 5 iterations. However it goes to infinity. How can I do that?
1) Keep a global variable, that increments from 0 to 5.
int i = 0;
2) Incement this variable inside your timer function..
-(void) yourFunction:(NSTimer*)timer{
//do your action
i++;
if(i == 5){
[timer invalidate];
}
}
3) When creating timer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10
target:self
selector:#selector(yourMethod:) // <== see the ':', indicates your function takes an argument
userInfo:nil
repeats:YES];
You should take one counter, increment it every time when your method get called, count for 5 and then invalidate your timer using below code.
[timer invalidate];
To destroy the timer from the current loop, you should call [timer invalidate];
To determine five occurrences, you need to maintain a variable and increment its count each time. If it is equal to 5, call invalidate method.
First of all you need to declare an int and declare your NSTimer *timer, so we can stop it:
#interface AppDelegate : UIViewController {
int myInt;
NSTimer *timer;
}
To start the NSTimer you'll need to change just a bit of the code:
timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(yourMethod) userInfo:nil repeats:YES];
Inside your void function you can make the verification to check if the code's running after 5 iterations:
- (void)myVoid{
NSLog(#"Call Me");
if (myInt == 5) {
[timer invalidate];
timer = nil;
}
myInt++;
}