Проблема NSTimer - PullRequest
       10

Проблема NSTimer

0 голосов
/ 19 марта 2011

В моем приложении я использовал приведенный ниже код с таймером, равным 1.0f/30.0f, что означало, что он вызывается 30 раз в секунду для вызова incrementSpeed.Я заметил в файле журнала, что значение moduloResult равно '0' в секунду, а incrementSpeed вызывается 30 раз каждые 5 секунд, но я хочу, чтобы он вызывал его только 1 раз каждые 5 секунд.1005 *

- (void)move:(NSTimer *)theTimer {

   // ...
    CGFloat moduloResult = (float)((int)time % (int)5);
    NSLog(@"mod = %f",moduloResult);

    if (!moduloResult) {
        [self incrementspeed];
    }

   //...

}

- (void)inctime:(NSTimer*) thetimer{
    time = time + 0.10f;
    timeLabel.text = [NSString stringWithFormat:@"%0.1f", time];
}


- (void)initializeTimer:(float)intero {
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:intero target:self 
                               selector:@selector(move:) userInfo:nil repeats:YES];
}

- (void)initializeTime {
     float theInter = 1.0f/10.0f;
     self.timescore = [NSTimer scheduledTimerWithTimeInterval:theInter target:self 
                                   selector:@selector(inctime:) userInfo:nil repeats:YES];
}

-(void)incspeed{

    deno += 0.01f;
    [fadeTimer invalidate];
    self.fadeTimer = nil;
    [self settheInterval:1.0f/deno];
    [self initializeTimer:[self gettheInterval]];
    NSLog(@"deno = %f", deno);

    NSLog(@"interv = %f", theInterval);

}

Ответы [ 3 ]

1 голос
/ 19 марта 2011

Через self.timescore, inctime: вызывается 10 раз в секунду.Каждый раз он увеличивает временную переменную на 0,1 секунды.Таким образом, переменная времени - это время в секундах с начала таймера, округленное с точностью до 0,1 секунды.Например, вы получили бы то же самое, если бы сделали:

... elsewhere ...
@property (nonatomic, assign) NSTimeInterval startTime;

- (void)initializeTime
{
    self.startTime = [NSDate timeIntervalSinceReferenceDate];
}

- (void)move:(NSTimer *)theTimer 
{
    NSTimeInterval timeSinceInitializeTimeWasCalled =
        [NSDate timeIntervalSinceReferenceData] - self.startTime;

    // round down the nearest multiple of 0.1 if necessary, e.g.
    timeSinceInitializeTimeWasCalled -=
                              fmod(timeSinceInitializeTimeWasCalled, 0.1);
}

Эта строка:

CGFloat moduloResult = (float)((int)time % (int)5);

Вызывается в методе, который, как вы заявляете, вызывается 30 раз в секунду.Учитывая, что оно положительное, (int) время округляет «время» до ближайшего целого числа.Таким образом, moduloResult будет равен «0» 30 раз - в период между вводом пятой секунды и выходом из нее снова.Что вы, вероятно, хотите, как намекнуло в коде, который я выложил выше, это:

CGFloat moduloResult = fmod(time, 5.0);

И даже тогда вы не хотите сравнивать результат напрямую с 0, потому что числа с плавающей запятой имеют тенденцию округлятьсяспособы, чтобы быть не точными.Если вы вызываете этот метод 30 раз в секунду, я вместо этого рекомендую:

CGFloat moduloResult = fmod(time + 1.0 / 60, 5.0);
if(moduloResult < 1.0 / 30.0)
{
}

Итак, вы проверяете, находится ли время в пределах 1/30 секунды, когда время мод 5 равно нулю.

1 голос
/ 19 марта 2011

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

Из-за различных источников входного сигнала Типичный цикл выполнения управляет, эффективное разрешение времени интервал для таймера ограничен порядка 50-100 миллисекунд. Если время срабатывания таймера происходит во время длинный вынос или пока цикл выполнения в режиме, который не контролирует таймер, таймер не срабатывает до в следующий раз цикл выполнения проверяет таймер. Поэтому фактическое время в который может сработать таймер значительный период времени после запланированное время стрельбы.

Итак, во-первых, вы не сможете иметь таймер, который запускается каждую 1/30 секунды. Даже 1/10 секунды, как вы говорите в своем коде, находится на грани возможного.

Также обратите внимание, что таймер все еще срабатывает, даже если уже поздно. Это может объяснить, почему вы видите срабатывание таймера по истечении времени, которое, по вашему мнению, должно быть.

0 голосов
/ 19 марта 2011

Если вы конвертируете число с плавающей запятой или двойное в целое, оно удаляет десятичные дроби.Так что время будет только целым числом.Таким образом, он всегда будет делить целое число на 5, что означает, что у вас никогда не будет модуля.Почему вы на самом деле конвертировали их в целые?Попробуйте сделать их обоих двойными и посмотрите, поможет ли это.Могу ошибаться, но я думаю, что это сработает.

...