NSTimer问题

时间:2011-03-19 15:48:52

标签: iphone objective-c timer nstimer ipod

在我的应用程序中,我使用下面的代码,其间隔等于1.0f/30.0f,这意味着每秒调用30次来调用incrementSpeed。我在日志文件中注意到moduloResult的值等于'0'一秒钟,incrementSpeed每5秒调用30次,但我希望它每次调用它只需1次5秒。

- (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 个答案:

答案 0 :(得分:1)

我不确定我是否完全明白你要做的是什么,但我可以说的是,当你处于精确度的边缘时,定时器的行为可能有点不可预测。而你正在这样做。 Here from the manual

  

由于各种输入源a   典型的运行循环管理,   有效解决时间问题   计时器的间隔限制为开启   50-100毫秒的顺序。如果一个   计时器的发射时间发生在   长标注或运行循环时   在一种不监控的模式下   计时器,直到计时器才开火   下次运行循环检查时   计时器。因此,实际时间在   计时器可能发射的是什么   是一段很长的一段时间   预定的开火时间。

首先,你不可能有一个每1/30秒运行一次的计时器。即使是1/10秒,这就是你在代码中所说的,也是可能的边缘。

另请注意,计时器仍然会闪光,即使它已经很晚了。这可以解释为什么你会在你想到它之后看到计时器开火。

答案 1 :(得分:1)

通过self.timescoreinctime:每秒调用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)
{
}

因此,当时间模式5为零时,您正在检查时间是否在1/30周围。

答案 2 :(得分:0)

如果将float或double转换为int,则会删除其小数。所以时间只是一个整数。所以它总是将整数除以5,这意味着你永远不会有模数。你为什么实际将它们转换为整数?尝试将它们都加倍,看看是否有帮助。可能会弄错,但我认为它会起作用。