How to display timer results on a label in xcode? - ios

I have added a simple timer in my app. At the moment the timer is just going from 00:00, 00:01, 00:02 and so on. When i complete a level i got to result screen which displays my score. Im still quite new to this and i was wondering how can i display the timer results.
This is the implementation of the timer:
//in .h file
IBOutlet UILabel *GameTimer;
int timeSec;
int timeMin;
NSTimer *timer;
//in .m file
-(void)startTimer1{
//Invalidate function stops 'timer1' before it is restarted
//initializing 'timer1'
timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerTick:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode];
}
//Event called every time the NSTimer ticks.
- (void)timerTick:(NSTimer *)timer1
{
timeSec++;
if (timeSec == 60)
{
timeSec = 0;
timeMin++;
}
//Format the string 00:00
NSString* timeNow = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
//Display on your label
//[timeLabel setStringValue:timeNow];
GameTimer.text= timeNow;
}
My attempt to display it on results screen but all i get is 0(dont mind the Spanish string just says how many points you got):
pointsInfo.text = [NSString stringWithFormat:#"¡Felicidades! ¡Has conseguido la máxima puntuación: %#! Debajo puedes encontrar las respuestas que has seleccionado:, time results: %# ",sc, timer1];
EDIT: Game1 is a viewController and so is gameResults1.
Game1 method:
// Method for starting 'timer1'
-(void)startTimer1{
//Invalidate function stops 'timer1' before it is restarted
//initializing 'timer1'
timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerTick:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode];
}
//Event called every time the NSTimer ticks.
- (void)timerTick:(NSTimer *)timer1
{
timeSec++;
if (timeSec == 60)
{
timeSec = 0;
timeMin++;
}
//Format the string 00:00
timeNow = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
//Display on your label
//[timeLabel setStringValue:timeNow];
GameTimer.text= timeNow;
}
//Call this to stop the timer event(could use as a 'Pause' or 'Reset')
- (void) StopTimer
{
[timer invalidate];
timeSec = 0;
timeMin = 0;
//Since we reset here, and timerTick won't update your label again, we need to refresh it again.
//Format the string in 00:00
timeNow = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
//Display on your label
// [timeLabel setStringValue:timeNow];
GameTimer.text= timeNow;
}
// #selector for 'timer1'
I dont think i have any particular way in calling game1 in gameresults1. other than:
#interface Game1Results : Game1

Create a global variable
#interface YourViewController ()
{
NSString *timeNow;
}
Now use this in your timerTick method.
timeNow = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
At the end, display score as
pointsInfo.text = timeNow;

The timer value is stored in timeMin and timeSec. You just have to get the timeMin and timeSec values to get your timer value.
NSString * resultTimer = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
NSLog(#"%#",resultTimer);
EDIT:
You can also implement a method stringValue :
-(NSString*)stringValue{
return [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
}
And call the method
[yourtimer stringValue];

Related

How to set progress bar With timer after view controller loaded

I m using timer on circular progress bar and taken NSDate property in interface (tested also taking in viewWillAppear) but when viewController loads it show starting from 27 seconds remain, while i have set its value to 30 seconds.
My scenario is, a user has a question and optional answers and he/she has some time suppose 30 seconds when he/she click start button than another screen opens after this screen loads time start should be from 30 seconds.
#interface TestViewController ()
{
NSTimeInterval totalCountdownInterval;
NSDate* startDate;
}
}
-(void)viewWillAppear:(BOOL)animated{
[self startTimer];
totalCountdownInterval = 30.0;
startDate = [NSDate date];
}
-(void)startTimer {
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
}
}
-(void)stopTimer {
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
}
-(void)timerFired:(NSTimer *)timer {
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate:startDate];
NSTimeInterval remainingTime = totalCountdownInterval - elapsedTime;
CGFloat timeRemain = remainingTime;
NSLog(#"%f", timeRemain);
if (remainingTime < 0.0) {
[_timer invalidate];
}
[_circleProgressBar setHintTextGenerationBlock:(^NSString *(CGFloat progress) {
if (!(timeRemain < 0.9)) {
progress = timeRemain - 1;
return [NSString stringWithFormat:#"%.0f", progress];
}else{
progress = 0;
return [NSString stringWithFormat:#"%.0f", progress];
}
})];
[_circleProgressBar setProgress:(_circleProgressBar.progress + 0.0333f) animated:YES];
}
-(void) viewWillDisappear:(BOOL)animated {
[self stopTimer];
}
Any help will be appreciated. Thanks.
The first timer event will be fired after 1 second is passed, so you should see 29 first. So you should display the number 30 manually somehow, outside the timer event.
And you subtract 1 in your code in setHintTextGenerationBlock :
progress = timeRemain - 1;
which will make you see 28 as initial.
And as final you should start timer in viewDidAppear instead of viewWillAppear where you lose another second and come to 27.
To correct code should be like:
#interface TestViewController ()
{
NSTimeInterval totalCountdownInterval;
NSDate* startDate;
}
}
-(void)viewDidLoad {
[_circleProgressBar setHintTextGenerationBlock:(^NSString *(CGFloat progress) {
return [NSString stringWithFormat:#"%.0f", progress * 30];
})];
[_circleProgressBar setProgress:1.0) animated:NO];
}
-(void)viewDidAppear:(BOOL)animated{
[self startTimer];
totalCountdownInterval = 30.0;
startDate = [NSDate date];
}
-(void)startTimer {
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
}
}
-(void)stopTimer {
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
}
-(void)timerFired:(NSTimer *)timer {
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate:startDate];
NSTimeInterval remainingTime = totalCountdownInterval - elapsedTime;
CGFloat timeRemain = remainingTime;
NSLog(#"%f", timeRemain);
if (remainingTime < 0.0) {
[_timer invalidate];
}
[_circleProgressBar setProgress:(1.0 * timeRemain / 30.0) animated:YES];
}
-(void) viewWillDisappear:(BOOL)animated {
[self stopTimer];
}
You should set progress to 1.0 in the beginning and count down to 0.0 in 30 steps.
Set hint generation block to display something meaningful for 1.0 - 0.0 as 30 - 0.
use that timer code in void view did appear and try once.
- (void)viewDidAppear:(BOOL)animated
{
[self startTimer];
totalCountdownInterval = 30.0;
startDate = [NSDate date];
}

Start and Stop functionality of StopWatch is not coordinated iOS

I am creating a stopwatch and the start and stop functionality is not coordinated. When the timer stops, it doesn't start where it left of.
The code looks like this:
self.endDate = [NSDate dateWithTimeIntervalSinceNow:12.0f*60.0f];
-(void)startPressed:(id)sender{
if(!_running){
_running = TRUE;
[sender setTitle:#"Stop" forState:UIControlStateNormal];
if (_stopTimer == nil) {
_stopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(changeTimer:)
userInfo:nil
repeats:YES];
}
}else{
_running = FALSE;
[sender setTitle:#"Start" forState:UIControlStateNormal];
[_stopTimer invalidate];
_stopTimer = nil;
}
}
- (void)changeTimer:(NSTimer*)timer {
_timeInterval = [self.endDate timeIntervalSinceNow];
self.timerControl1.minutesOrSeconds = ((NSInteger)_timeInterval)%60;
self.timerControl2.minutesOrSeconds = (NSInteger)(_timeInterval/60.0f);
self.timerControl3.minutesOrSeconds = ((NSInteger)_timeInterval)%60;
}
I know it is because of timeIntervalSinceNow. But, how to change this? Need some guidance on this.
The problem:
When you stop the stopwatch and start it again after 3s for example, it shld still start back from the same timing. but both my code, the start and stop timing are different, they are starting from a different timing. Need help to solve this.
don't use the endDate in changeTimer but use the endDate only to init the timer
#import "RimsViewController.h"
#interface RimsViewController ()
#property(weak) IBOutlet UILabel *label;
#property(strong) NSDate *endDate;
#end
#implementation RimsViewController {
BOOL _running;
NSTimeInterval _timeInterval;
NSTimer *_stopTimer;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.endDate = [NSDate dateWithTimeIntervalSinceNow:10*60];
_timeInterval = [self.endDate timeIntervalSinceNow];
}
-(IBAction)startPressed:(id)sender{
if(!_running){
_running = TRUE;
[sender setTitle:#"Stop" forState:UIControlStateNormal];
if (_stopTimer == nil) {
_stopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(changeTimer:)
userInfo:nil
repeats:YES];
}
}else{
_running = FALSE;
[sender setTitle:#"Start" forState:UIControlStateNormal];
[_stopTimer invalidate];
_stopTimer = nil;
}
}
- (void)changeTimer:(NSTimer*)timer {
_timeInterval -= 1;// [self.endDate timeIntervalSinceNow];
NSUInteger secs = _timeInterval;
int h = (NSUInteger)secs/3600;
secs-=h*3600;
int m = (NSUInteger)secs/60;
secs-=m*60;
int s = secs;
self.label.text = [NSString stringWithFormat:#"%d / %d / %d", h, m, s];
}
#end

Stopwatch counting in powers of 2

I am making a stopwatch in Objective-C:
- (void)stopwatch
{
NSInteger hourInt = [hourLabel.text intValue];
NSInteger minuteInt = [minuteLabel.text intValue];
NSInteger secondInt = [secondLabel.text intValue];
if (secondInt == 59) {
secondInt = 0;
if (minuteInt == 59) {
minuteInt = 0;
if (hourInt == 23) {
hourInt = 0;
} else {
hourInt += 1;
}
} else {
minuteInt += 1;
}
} else {
secondInt += 1;
}
NSString *hourString = [NSString stringWithFormat:#"%d", hourInt];
NSString *minuteString = [NSString stringWithFormat:#"%d", minuteInt];
NSString *secondString = [NSString stringWithFormat:#"%d", secondInt];
hourLabel.text = hourString;
minuteLabel.text = minuteString;
secondLabel.text = secondString;
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(stopwatch) userInfo:nil repeats:YES];
}
The stopwatch has three separate labels, if you were wondering, for hours, minutes and seconds. However, instead on counting by 1, it counts like 2, 4, 8, 16, etc.
Also, another issue with the code (quite a minor one) is that it doesn't display all numbers as two digits. For example it's shows the time as 0:0:1, not 00:00:01.
Any help is really appreciated! I should add that I am really new to Objective-C so keep it as simple as possible, thank you!!
Don't use repeats:YES if you schedule the timer at every iteration.
You're spawning one timer at every iteration and the timer is already repeating, resulting in an exponential growth of timers (and consequently of method calls to stopwatch).
Change the timer instantiation to:
[NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(stopwatch)
userInfo:nil
repeats:NO];
or start it outside the stopwatch method
For the second issue simply use a proper format string.
NSString *hourString = [NSString stringWithFormat:#"%02d", hourInt];
NSString *minuteString = [NSString stringWithFormat:#"%02d", minuteInt];
NSString *secondString = [NSString stringWithFormat:#"%02d", secondInt];
%02d will print a decimal number padding it with 0s up to length 2, which is precisely what you want.
(source)
For the first issue, instead of creating a timer instance for every call.Remove the line
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(stopwatch) userInfo:nil repeats:YES];
from the function stopwatch.
Replace your call to function stopwatch with the line above. i.e replace
[self stopwatch]
with
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(stopwatch) userInfo:nil repeats:YES];

NSTimer Pause timer [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to Pause/Play NSTimer?
I have three buttons start stop and pause..My start and stop button is working fine with the below code..but when press Pause it pause the timer..but when again i Press start.IT continues from the new added time ...not from the pause time....
supoose i pause at 5 second of start and wait for 5 sec then press start...it should display 5 ...but displaying 10..
because I have not mentioned (timer:) in timer!=nill of start...
how it will be add..
I have problems:
Pause not working.
-(void)start:(NSTimer *)timer
{
if(_timer==nil)
{
startDate =[NSDate date];
_timer=[NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(timer:) userInfo:nil repeats:YES];
}
if(_timer!=nil)
{
float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[_timer setFireDate:[previousFireDate initWithTimeInterval:pauseTime sinceDate:previousFireDate]];
}
}
-(void)timer:(NSTimer *)timer
{
NSInteger secondsSinceStart = (NSInteger)[[NSDate date] timeIntervalSinceDate:startDate];
NSInteger seconds = secondsSinceStart % 60;
NSInteger minutes = (secondsSinceStart / 60) % 60;
NSInteger hours = secondsSinceStart / (60 * 60);
NSString *result = nil;
if (hours > 0)
{
result = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
}
else
{
result = [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
}
label.text=result;
NSLog(#"time interval -> %#",result);
}
-(void)stop
{
if(_timer!=nil)
{
startDate=nil;
[_timer invalidate];
_timer = nil;
}
}
-(void)pause:(NSTimer *)timer
{
pauseStart = [NSDate dateWithTimeIntervalSinceNow:0];
previousFireDate = [_timer fireDate];
[_timer setFireDate:[NSDate distantFuture]];
}
-(void)pause:(NSTimer *)timer
{
pauseStart = [NSDate dateWithTimeIntervalSinceNow:0];
previousFireDate = [_timer fireDate];
//[timer setFireDate:[NSDate distantFuture]];
[_timer setFireDate:[NSDate distantFuture]];
}
Here is the code that I used for a timer:
I store all the components for the time, in my (singleton) class, the hour, minute, seconds value.
And, I simply "invalidate" the timer in the "pause" method, AND I store the values.
See, if this helps.
-(void) startTimer
{
NSLog(#"Values for timer: %d H, %d M, %d S", self.hours, self.minutes, self.seconds);
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
}
-(void) pauseTimer
{
if(_timer)
{
[_timer invalidate];
}
_timer = nil;
self.hour = hourValue;
self.minute = minuteValue;
self.second = secondsValue;
}

iOS Label Text Based On Timed Function

I've been trying to create a script that sets a timer and reduces a value by 33 each time it runs. In theory the timer should stop itself after 6 runs, but it keeps going and reaches negative values. Is there a reason for this?
-(void)checkValue:(NSTimer *)myTimer{
if(pplint > 0){
pplint = pplint-33;
NSString *ppllefttext = [NSString stringWithFormat:#"%d", pplint];
peopleleft.text = ppllefttext;
NSLog(#"Reduced Timer");
}
if(pplint < 0){
NSLog(#"Stop Timer");
[myTimer invalidate];
}
}
- (IBAction)gotocongrats{
pplint = 198;
NSString *ppllefttext = [NSString stringWithFormat:#"%d", pplint];
peopleleft.text = ppllefttext;
NSTimer * myTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(checkValue:)
userInfo:nil
repeats:YES];
NSLog(#"Started Timer");
}
I took you code and edited it a bit and it works just fine for me.
-(void)checkValue:(NSTimer *)myTimer{
if(pplint > 0){
pplint = pplint-33;
NSLog(#"%i",pplint);
NSLog(#"Reduced Timer");
}
if(pplint <= 0){
NSLog(#"Stop Timer");
[myTimer invalidate];
}
}
- (IBAction)gotocongrats{
pplint = 198;
NSTimer * myTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(checkValue:)
userInfo:nil
repeats:YES];
NSLog(#"Started Timer");
}

Resources