Кнопка запуска секундомера сбрасывает таймер

Я делаю простой секундомер, однако каждый раз, когда я запускаю таймер, нажимаю «Стоп» и запускаю снова, желая продолжить мой таймер, часы перезапускаются с 0. Я не совсем уверен, что делать, поскольку я только что поднял объект. 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

В настоящее время я нахожусь в этой точке, где мое начало

#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

person tbreinhart    schedule 15.04.2014    source источник
comment
Кажется, проблема именно в этой строке: totalTimeInterval = timeInterval; Вы сбрасываете totalTimeInterval каждый раз вместо добавления нового временного интервала к текущей сумме.   -  person Vlad Papko    schedule 15.04.2014
comment
@VladimirPopko, этот код не проблема. totalTimeInterval означает разницу между временем начала и текущим временем, что и происходит. Проблема в том, что время запуска сбрасывается каждый раз, когда запускается таймер.   -  person Dima    schedule 15.04.2014


Ответы (2)


Каждый раз, когда вы нажимаете «Пуск», запускается этот код:

self.startDate = [NSDate date];

Это сбрасывает время начала, которое вы используете. Переместите это куда-нибудь, чтобы это происходило только один раз, а не каждый раз, когда вы запускаете таймер, и я думаю, что результат будет ближе к тому, что вы хотите. Возможно, вы можете просто сохранить дополнительный BOOL, который переключается при первом запуске таймера.

Изменить:

Очень хороший момент, поднятый Stonz2, который я упустил из виду. Если вы сделаете это таким образом, время будет пропущено, как только вы запустите его обратно. Чтобы исправить это, вам нужно будет сохранить отдельный NSDate, когда вы останавливаете таймер, чтобы представить время «паузы». Затем, когда вы снова запускаете таймер, вам нужно будет добавить время «паузы» к времени «старта», чтобы продолжение было плавным.

Изменить2:

Я бросил это в проект, и вот некоторый рабочий код.

Я добавил дополнительное свойство:

@property (nonatomic, strong) NSDate *pauseDate;

В onStopPressed: я добавил это, чтобы инициализировать время паузы:

_pauseDate = [NSDate date];

Затем в onStartPressed: я добавил следующий код, чтобы обеспечить однократную инициализацию startDate и выполнить математические расчеты, чтобы получить прошедшее время после паузы:

    // 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;
        }
    }

Также, чтобы ваш сброс работал правильно, в onResetPressed: вам нужно будет добавить:

_startDate = nil;
_pauseDate = nil;

Только что проверил это, и это работает как чемпион.

Edit3: полный метод в соответствии с веткой комментариев

- (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;

    }
}
person Dima    schedule 15.04.2014
comment
Это не будет учитывать время паузы, если Том вычисляет свое общее время так же, как он просто вычисляет current time - start time. - person Stonz2; 15.04.2014
comment
@ Stonz2 Stonz2 Это хороший момент, я учту это в своем ответе. - person Dima; 15.04.2014
comment
@Dima, возможно, я делаю что-то не так, потому что, когда я нажимаю «Пуск», после применения этого кода ничего не происходит. - person tbreinhart; 15.04.2014
comment
@Dima Думаю, больше, где вы добавляете этот код, упомянутый выше, в мой onStartPressed - person tbreinhart; 15.04.2014
comment
@TomReinhart, вы помещаете его в первый оператор if, прежде чем инициализировать новый таймер. Дайте мне знать, если это не имеет смысла, и я опубликую весь метод, я просто пытался сделать его простым. - person Dima; 15.04.2014
comment
@ Дима, да, извини, я новичок, как ты видишь. Я попытался вставить его таким образом и получил исходную ошибку. Да, я был бы признателен только за этот метод. спасибо дима - person tbreinhart; 15.04.2014
comment
@TomReinhart Я добавил это внизу своего ответа. - person Dima; 15.04.2014
comment
@Дима спасибо большое. вы были очень полезны. - person tbreinhart; 15.04.2014

Это потому, что вы сбрасываете self.startDate в методе onStartPressed. Делайте это только в viewDidLoad: и в onResetPressed:

person Levi    schedule 15.04.2014