I am making a basic stopwatch, however, each time I start the timer, click stop, and start again wanting to continue my timer, the clock restarts at 0. I'm not quite sure what to do as I just picked up obj-c/Xcode.
#import "StopwatchViewController.h"
bool stopPressed = false;
bool startPressed = false;
int startsPressed = 0;
NSTimeInterval totalTimeInterval;
#interface StopwatchViewController ()
#property (strong, nonatomic) NSTimer *stopWatchTimer; // Store the timer that fires after a certain time
#property (strong, nonatomic) NSDate *startDate; // Stores the date of the click on the start button
#end
#implementation StopwatchViewController
- (void)updateTimer
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate: self.startDate];
totalTimeInterval = timeInterval;
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:totalTimeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat: #"HH:mm:ss.SSS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormatter stringFromDate:timerDate];
self.stopwatchLabel.text = timeString;
}
- (IBAction)onStartPressed:(id)sender
{
if(startsPressed < 1) {
if(startPressed) return;
startPressed = true;
stopPressed =false;
self.startDate = [NSDate date];
//create the stop watch timer that fires every 100ms
self.stopWatchTimer =
[NSTimer scheduledTimerWithTimeInterval:1.0/100.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
} else {
startPressed = true;
stopPressed = false;
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)onStopPressed:(id)sender {
if(stopPressed) return;
stopPressed = true;
startPressed = false;
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
}
- (IBAction)onResetPressed:(id)sender {
if(stopPressed == false) return;
self.stopWatchTimer = 0;
NSString *timeString = #"00:00:00.000";
self.stopwatchLabel.text = timeString;
}
#end
I am currently at this point where my start
#import "StopwatchViewController.h"
bool stopPressed = false;
bool startPressed = false;
int startsPressed = 0;
NSTimeInterval totalTimeInterval;
#interface StopwatchViewController ()
#property (strong, nonatomic) NSTimer *stopWatchTimer; // Store the timer that fires after a certain time
#property (strong, nonatomic) NSDate *startDate; // Stores the date of the click on the start button
#property (nonatomic, strong) NSDate *pauseDate;
#end
#implementation StopwatchViewController
- (void)updateTimer
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate: self.startDate];
totalTimeInterval = timeInterval;
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:totalTimeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat: #"HH:mm:ss.SSS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormatter stringFromDate:timerDate];
self.stopwatchLabel.text = timeString;
}
- (IBAction)onStartPressed:(id)sender
{
// if(startsPressed < 1) {
// if(startPressed) return;
// startPressed = true;
// stopPressed =false;
// self.startDate = [NSDate date];
//
// //create the stop watch timer that fires every 100ms
// self.stopWatchTimer =
// [NSTimer scheduledTimerWithTimeInterval:1.0/100.0
// target:self
// selector:#selector(updateTimer)
// userInfo:nil
// repeats:YES];
// } else {
//
// startPressed = true;
// stopPressed = false;
//
// }
if(startsPressed < 1) {
if( ! _startDate) {
self.startDate = [NSDate date];
}
else {
if(_pauseDate) {
NSTimeInterval startTime = _startDate.timeIntervalSince1970;
NSTimeInterval pauseTime = _startDate.timeIntervalSince1970;
// the actual elapsed time before we paused
NSTimeInterval elapsedTime = pauseTime - startTime;
// set a new start time to match our elapsed time.
NSTimeInterval currentTime = [NSDate date].timeIntervalSince1970;
NSTimeInterval newStartTime = currentTime - elapsedTime;
_startDate = [NSDate dateWithTimeIntervalSince1970:newStartTime];
_pauseDate = nil;
}
}
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)onStopPressed:(id)sender {
if(stopPressed) return;
_pauseDate = [NSDate date];
stopPressed = true;
startPressed = false;
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
}
- (IBAction)onResetPressed:(id)sender {
if(stopPressed == false) return;
_startDate = nil;
_pauseDate = nil;
self.stopWatchTimer = 0;
NSString *timeString = #"00:00:00.000";
self.stopwatchLabel.text = timeString;
}
#end
Every time you hit "start", this code gets run:
self.startDate = [NSDate date];
This resets the start time you are using. Move that out somewhere so that it only happens once instead of on every time you start the timer and I think the result will be closer to what you want. Perhaps you can just store an extra BOOL that gets switched the first time the timer is started.
Edit:
Very good point brought up by Stonz2 that I overlooked. Doing it this way will cause the time to skip once you start it back up. In order to fix this you will need to store a separate NSDate when you stop the timer, to represent the "paused" time. Then, when you are starting the timer back up again, you will need to add the "paused" time to the "start" time so that the continuation is fluid.
Edit2:
I threw this into a project and here is some working code.
I added an extra property:
#property (nonatomic, strong) NSDate *pauseDate;
In onStopPressed:, I added this to initialize the pause time:
_pauseDate = [NSDate date];
Then, in onStartPressed:, I added the following code to ensure a single initialization of the startDate and to do the math to get the elapsed time after pausing:
// if we have a start date, don't initialize again
if(! _startDate)
{
self.startDate = [NSDate date];
}
else
{
if(_pauseDate)
{
NSTimeInterval startTime = _startDate.timeIntervalSince1970;
NSTimeInterval pauseTime = _pauseDate.timeIntervalSince1970;
// The actual elapsed time before we paused.
NSTimeInterval elapsedTime = pauseTime - startTime;
// Set a new start time to match our elapsed time.
NSTimeInterval currentTime = [NSDate date].timeIntervalSince1970;
NSTimeInterval newStartTime = currentTime - elapsedTime;
_startDate = [NSDate dateWithTimeIntervalSince1970:newStartTime];
_pauseDate = nil;
}
}
Also, in order to make your reset work correctly, in onResetPressed: you will need to add:
_startDate = nil;
_pauseDate = nil;
Just tested this and it works like a champ.
Edit3: full method as per comment thread
- (IBAction)onStartPressed:(id)sender
{
if(startsPressed < 1) {
if(startPressed) return;
startPressed = true;
stopPressed =false;
if(! _startDate)
{
self.startDate = [NSDate date];
}
else
{
if(_pauseDate)
{
NSTimeInterval startTime = _startDate.timeIntervalSince1970;
NSTimeInterval pauseTime = _pauseDate.timeIntervalSince1970;
NSTimeInterval elapsedTime = pauseTime - startTime;
NSTimeInterval currentTime = [NSDate date].timeIntervalSince1970;
NSTimeInterval newStartTime = currentTime - elapsedTime;
_startDate = [NSDate dateWithTimeIntervalSince1970:newStartTime];
_pauseDate = nil;
}
}
//create the stop watch timer that fires every 100ms
self.stopWatchTimer =
[NSTimer scheduledTimerWithTimeInterval:1.0/100.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
} else {
startPressed = true;
stopPressed = false;
}
}
It is because you reset self.startDate in the onStartPressed method. Do this only in viewDidLoad: and in onResetPressed:
Related
I have a NSTimer that functions as a stopwatch. It makes the time count and has the pause function that works properly but the function does not work continue. The timer seems to be counting even paused but not updated the label and when I touch the button comes down to is to continue from where you left it continues counting that did not stop. How can I fix this?
this is my chronometer code:
- (void)viewDidLoad {
[super viewDidLoad];
[self setUp];
self.isPaused = NO;
}
- (void) setUp {
startDate = [NSDate date];
_timer = [NSTimer scheduledTimerWithTimeInterval: 1.0/100.0 target: self selector: #selector(timerUpdating) userInfo: nil repeats: true];
}
-(void)timerUpdating {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormater = [[NSDateFormatter alloc]init];
[dateFormater setDateFormat:#"mm:ss"];
[dateFormater setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormater stringFromDate:timerDate];
if (self.isPaused == NO){
_timerLabel.text = timeString;
}
}
- (IBAction)pauseAction:(id)sender {
[self pauseTimer:self.timer];
}
- (IBAction)resumeAction:(id)sender {
[self resumeTimer:self.timer];
}
-(void) pauseTimer:(NSTimer *)timer {
self.isPaused = YES;
self.pauseStart = [NSDate date];
self.previousFireDate = [timer fireDate];
[timer setFireDate:[NSDate distantFuture]];
}
-(void) resumeTimer:(NSTimer *)timer {
self.isPaused = NO;
NSDate *currentDate = [NSDate date];
NSTimeInterval pauseTime = [currentDate timeIntervalSinceDate:pauseStart];
NSDate *neededFireDate = [NSDate dateWithTimeInterval:pauseTime sinceDate:previousFireDate];
[timer setFireDate:neededFireDate];
NSLog(#"Fire Date: %#", timer.fireDate);
}
At timerUpdating you set NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];. This will not take into account if the user paused the timer or not.
To correct this behavior you could do something like:
In .h (set a member variable):
NSTimeInterval pausedTime;
In .m (3 lines edited)
- (void)viewDidLoad {
[super viewDidLoad];
[self setUp];
self.isPaused = NO;
pausedTime = 0; //edit
}
- (void) setUp {
startDate = [NSDate date];
_timer = [NSTimer scheduledTimerWithTimeInterval: 1.0/100.0 target: self selector: #selector(timerUpdating) userInfo: nil repeats: true];
}
-(void)timerUpdating {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate] - pauseTime;//edit
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormater = [[NSDateFormatter alloc]init];
[dateFormater setDateFormat:#"mm:ss"];
[dateFormater setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormater stringFromDate:timerDate];
if (self.isPaused == NO){
_timerLabel.text = timeString;
}
}
- (IBAction)pauseAction:(id)sender {
[self pauseTimer:self.timer];
}
- (IBAction)resumeAction:(id)sender {
[self resumeTimer:self.timer];
}
-(void) pauseTimer:(NSTimer *)timer {
self.isPaused = YES;
self.pauseStart = [NSDate date];
self.previousFireDate = [timer fireDate];
[timer setFireDate:[NSDate distantFuture]];
}
-(void) resumeTimer:(NSTimer *)timer {
self.isPaused = NO;
NSDate *currentDate = [NSDate date];
NSTimeInterval pauseTime = [currentDate timeIntervalSinceDate:pauseStart];
pausedTime += pauseTime;//edit
NSDate *neededFireDate = [NSDate dateWithTimeInterval:pauseTime sinceDate:previousFireDate];
[timer setFireDate:neededFireDate];
NSLog(#"Fire Date: %#", timer.fireDate);
}
My main storyboard has a stopwatch. I can start the watch, and then navigate to another storyboard. When I return to the main stopwatch storyboard it has stopped and reset to zero. Please help me figure out how to keep the stopwatch going forever until I press STOP. Thanks
All storyboards have same controller
here is the .h
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController{
UILabel *lbl;
NSTimer *stopTimer;
NSDate *startDate;
BOOL running;
}
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
#property (strong,nonatomic) IBOutlet UILabel *lbl;
-(IBAction)startPressed:(id)sender;
-(IBAction)resetPressed:(id)sender;
-(void)updateTimer;
#end
here is the .m
#import "MainViewController.h"
#import "SWRevealViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize lbl;
- (void)viewDidLoad
//stopwatch open
{
[super viewDidLoad];
lbl.text = #"00.00.00.000";
running = FALSE;
startDate = [NSDate date];
//stopwatch close
[super viewDidLoad];
self.title = #"therapyTools";
// Change button color
_sidebarButton.tintColor = [UIColor colorWithWhite:0.1f alpha:0.9f];
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
_sidebarButton.target = self.revealViewController;
_sidebarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//stopwatch open
-(IBAction)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(updateTimer)
userInfo:nil
repeats:YES];
}
}else{
running = FALSE;
[sender setTitle:#"START" forState:UIControlStateNormal];
[stopTimer invalidate];
stopTimer = nil;
}
}
-(void)updateTimer{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.SSS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString=[dateFormatter stringFromDate:timerDate];
lbl.text = timeString;
}
-(IBAction)resetPressed:(id)sender{
[stopTimer invalidate];
stopTimer = nil;
startDate = [NSDate date];
lbl.text = #"00.00.00.000";
running = FALSE;
}
//stopwatch close
#end
I discovered an issue with my sample project. I simply create a scheduledTimer that "animate" a label and then, when I reached the result I want, I invalidate the timer and I set an another one, this time as a "clock".
This is the code I use
//
// ViewController.m
//
//
//
//
//
#import "ViewController.h"
#define ANIMATION_INTERVAL 0.07 // in secondi
#define ANIMATION_DURATION 1 // in secondi
#interface ViewController ()
{
int contatore;
NSString *hour;
NSString *minute;
NSString *second;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
contatore = 0;
[self startTimeAnimation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)startTimeAnimation
{
NSTimer * animationTimer = [NSTimer scheduledTimerWithTimeInterval:ANIMATION_INTERVAL target:self selector:#selector(timeout:) userInfo:nil repeats:YES];
}
-(void)timeout: (NSTimer *)timer
{
// Simulate of the Timer Duration with a counter
if (contatore < ceilf(ANIMATION_DURATION/ANIMATION_INTERVAL))
{
// Proceed with animation
contatore++;
int tempHour = arc4random_uniform(24);
int tempMinute = arc4random_uniform(60);
int tempSecond = arc4random_uniform(60);
if (tempHour < 10)
{
hour = [NSString stringWithFormat:#"0%d", tempHour];
}
else
{
hour = [NSString stringWithFormat:#"%d", tempHour];
}
if (tempMinute < 10)
{
minute = [NSString stringWithFormat:#"0%d", tempMinute];
}
else
{
minute = [NSString stringWithFormat:#"%d", tempMinute];
}
if (tempSecond < 10)
{
second = [NSString stringWithFormat:#"0%d", tempSecond];
}
else
{
second = [NSString stringWithFormat:#"%d", tempSecond];
}
_orarioLbl.text = [NSString stringWithFormat:#"%#:%#:%#", hour, minute, second];
}
else
{
// Stops animation
[timer invalidate];
[timer release];
contatore = 0;
[self setActualTime];
// Starts clock
NSTimer *clockTimer = [NSTimer timerWithTimeInterval:.5f target:self selector:#selector(updateClock) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:clockTimer forMode:NSRunLoopCommonModes];
}
}
-(void)updateClock
{
[self setActualTime];
}
-(void)setActualTime
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH"];
hour = [dateFormatter stringFromDate:[NSDate date]];
[dateFormatter setDateFormat:#"mm"];
minute = [dateFormatter stringFromDate:[NSDate date]];
[dateFormatter setDateFormat:#"ss"];
second = [dateFormatter stringFromDate:[NSDate date]];
_orarioLbl.text = [NSString stringWithFormat:#"%#:%#:%#", hour, minute, second];
[dateFormatter release];
}
#end
Since I start the "clock", memory still stays on 19/20 MB with constant persistent allocation. When the timer updates the minute value, persistent allocations increase as you can see in the gif! How is it possible? However, also 19MB of memory is too much for a simple clock, isn't it?
Profiling on Instruments, the new allocations are all about CoreGraphics!
EDIT I tested it on another device and the persistent allocations decreased. I don't know why, but I solved in this way. Thanks
NSTimer retains its target and that may lead to a retain cycle. Grab a weak reference to self and set that as the target:
__weak typeof(self) weakSelf = self;
NSTimer * animationTimer = [NSTimer scheduledTimerWithTimeInterval:ANIMATION_INTERVAL target:weakSelf selector:#selector(timeout:) userInfo:nil repeats:YES];
and
__weak typeof(self) weakSelf = self;
NSTimer *clockTimer = [NSTimer timerWithTimeInterval:.5f target:weakSelf selector:#selector(updateClock) userInfo:nil repeats:YES];
May I also recommend you create a property for the dateFormatter, as NSDateFormatters are expensive to create. And why are you releasing the dateFormatter? Are you not using ARC?
I have an NSTimer which I pause and resume with the following methods respectively:
-(void) pauseTimer:(NSTimer *)timer {
self.scene.paused = YES;
pauseStart = [NSDate date];
previousFireDate = [timer fireDate];
[timer setFireDate:[NSDate distantFuture]];
}
-(void) resumeTimer:(NSTimer *)timer {
self.scene.paused = NO;
NSDate *currentDate = [NSDate date];
NSTimeInterval pauseTime = [currentDate timeIntervalSinceDate:pauseStart];
NSDate *neededFireDate = [NSDate dateWithTimeInterval:pauseTime sinceDate:previousFireDate];
[timer setFireDate:neededFireDate];
NSLog(#"Fire Date: %#", timer.fireDate); //returning null
}
It is not properly resetting the fire date because when I check timer.fireDate, it says null. All we want is for these methods to pause the timer and resume the timer where it left off when the resume method is called. Any help is greatly appreciated.
My solution differs from yours in one major thing. I recreate a timer when it resumes. Here is how I do it and it's been working quite well:
#property (nonatomic, strong) NSTimer *timer;
#property (nonatomic, assign) NSTimeInterval elapsedTime;
#property (nonatomic, strong) NSDate *startDate;
- (void)startTimer
{
NSTimeInterval timeInterval = 20.0f;
// Create a timer. Adjust the elapsed time.
_timer = [NSTimer scheduledTimerWithTimeInterval:(timeInterval - _elapsedTime)
target:self
selector:#selector(timerFireMethod:)
userInfo:nil
repeats:YES];
// Save the start date.
_startDate = [NSDate date];
}
- (void)timerFireMethod:(NSTimer *)theTimer
{
// Clean.
[_timer invalidate];
_timer = nil;
_elapsedTime = 0.0;
[self startTimer];
// Additional handling.
}
- (void)pauseTimer
{
// Clean.
[_timer invalidate];
_timer = nil;
// Save the elapsed time.
_elapsedTime = [[NSDate date] timeIntervalSinceDate:_startDate];
}
Hope it helps.
I are trying to make to a stopwatch app and facing problems getting it to work properly. When I start the stopwatch and stop and start off again, it doesn't continue from where it left off. It carries on running as if it didn't stop. Need some guidance on getting it work properly. I have been trying since morning, the rest of the functions i have made as similar to the apple's stopwatch, only this is bugging me.. Appreciate any help...
The code looks like this:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
UILabel *lbl;
NSTimer *stopTimer;
NSDate *startDate,*currentDate;
BOOL running;
UIButton *bttn;
NSMutableArray *tableItems;
NSString *timeString,*currentString;
UITableView *tableview;
int counter;
}
#property (strong,nonatomic) IBOutlet UILabel *lbl;
#property (strong,nonatomic) IBOutlet UIButton *bttn;
#property (strong,nonatomic) NSMutableArray *tableItems;
#property (strong,nonatomic) NSString *timeString;
#property (strong,nonatomic) IBOutlet UITableView *tableview;
-(IBAction)startPressed:(id)sender;
-(IBAction)resetPressed:(id)sender;
-(void)updateTimer;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize lbl,bttn,tableItems,timeString,tableview;
- (void)viewDidLoad
{
[super viewDidLoad];
lbl.text = #"00.00.00.0";
running = FALSE;
//difference = #"0";
startDate = [NSDate date];
tableItems = [[NSMutableArray alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)startPressed:(id)sender{
if(!running){
running = TRUE;
[sender setTitle:#"Stop" forState:UIControlStateNormal];
[bttn setTitle:#"Lap" forState:UIControlStateNormal];
if (stopTimer == nil) {
stopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
}else{
running = FALSE;
//startDate = currentDate;
//difference = currentString;
[sender setTitle:#"Start" forState:UIControlStateNormal];
[bttn setTitle:#"Restart" forState:UIControlStateNormal];
[stopTimer invalidate];
stopTimer = nil;
}
}
-(void)updateTimer{
currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.S"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
timeString=[dateFormatter stringFromDate:timerDate];
lbl.text = timeString;
}
-(IBAction)resetPressed:(id)sender{
if (!running) {
[stopTimer invalidate];
stopTimer = nil;
tableItems = [[NSMutableArray alloc] init];
startDate = [NSDate date];
lbl.text = #"00.00.00.0";
running = FALSE;
}
else{
[tableItems insertObject:timeString atIndex:0];
[tableview reloadData];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return tableItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Step 1:Check whether if we can reuse a cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
//Step2: If there are no new cells to reuse,create a new one
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:#"cell"];
}
//Step 3: Set the cell text content
cell.textLabel.text = [tableItems objectAtIndex:indexPath.row];
//Step 4: Return the row
return cell;
}
#end
In your updateTimer method you calculate the time difference between startDate and the current date. You don't take into account that you would have to subtract the time that passed while the stopwatch was stopped.
Edit:
I'd suggest to sum up and save all timeIntervals that pass between start and stop
Add a property NSTimeInterval timePassed to your class and modify your code like this:
- (void)viewDidLoad
{
//...
timePassed = 0;
}
-(IBAction)startPressed:(id)sender{
if(!running){
//...
startDate = [NSDate date];
//...
}else{
NSDate *currentDate = [NSDate date];
NSTimeInterval intervalToAdd = [currentDate timeIntervalSinceDate:startDate];
timePassed += intervalToAdd;
//...
}
-(void)updateTimer{
currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
timeInterval += timePassed; // <<<<<
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.S"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
timeString=[dateFormatter stringFromDate:timerDate];
lbl.text = timeString;
}
-(IBAction)resetPressed:(id)sender{
if (!running) {
//...
timePassed = 0;
//...
}
//...
}
Quoting some code inside my active project.
NSDate *timeStart = [NSDate dateWithTimeIntervalSince1970:0];
NSDate *timeEnd = [timeStart dateByAddingTimeInterval:_timePassed];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"00:00:00"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSString *strDate = [dateFormatter stringFromDate:timeEnd];
_timeLabel.text = strDate;
This is how I did mine. If you want to use UILabel as a stopwatch, MZTimerLabel is a awesome two line solution for you. Take a look.
Cheers.