Question

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
Était-ce utile?

La solution

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;

    }
}

Autres conseils

It is because you reset self.startDate in the onStartPressed method. Do this only in viewDidLoad: and in onResetPressed:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top