更改重复计时器的NSTimer间隔

时间:2010-06-09 09:29:58

标签: cocoa macos timer

我在Cocoa中使用如下设置的NSTimer运行mainLoop:

        mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/fps target:self selector:@selector(mainloop) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode];

在程序启动时,我将timeInterval设置为0.0,以便mainloop尽可能快地运行。无论如何,我想提供一个函数来在运行时将帧速率(以及计时器的时间间隔)设置为特定值。不幸的是,据我所知,这意味着我必须重新初始化计时器,因为Cocoa不提供像“setTimerInterval”这样的函数 这就是我试过的:

    - (void)setFrameRate:(float)aFps
{
    NSLog(@"setFrameRate");
    [mainLoopTimer invalidate];
    mainLoopTimer = nil;

    mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/aFps target:self selector:@selector(mainloop) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode];
}

但是会抛出以下错误并停止主循环:

  

2010-06-09 11:14:15.868 myTarget [7313:a0f] setFrameRate   2010-06-09 11:14:15.868 myTarget [7313:a0f] * __NSAutoreleaseNoPool():类__NSCFDate的对象0x40cd80自动释放,没有池到位 - 只是泄漏   2010-06-09 11:14:15.869 myTarget [7313:a0f] * __NSAutoreleaseNoPool():类NSCFTimer的对象0x40e700自动释放,没有池到位 - 只是泄漏   0.614628

我还尝试使用“retain”关键字重新创建计时器,但这并未改变任何内容。 有关如何在运行时动态更改NSTimer间隔的任何想法吗?

谢谢!

3 个答案:

答案 0 :(得分:3)

我知道,这个线程太棒了! 但我也在寻找功能!

事实证明,NSTimes没有提供此功能,我决定建立一个自己的功能。 这不是最好的解决方案,但就我而言,它是唯一可行的解​​决方案。

我定义了变量“BOOL keepOn;”在我的标题中。

-(IBAction)doSomething:(id)sender
{
    // Any action to throw every interval.
}

-(IBAction)switchAutoLoad:(id)sender
{
    if([autoLoad state] == NSOffState)
    {
        NSLog(@"auto-reload on!");

        self performSelector:@selector(fireTimer) withObject:nil afterDelay:0];
        keepOn = YES;
        [autoLoad setState:NSOnState];
    }
    else
    {
        NSLog(@"auto-reload off!");
        keepOn = NO;
        [autoLoad setState:NSOffState];
    }
}

-(void)fireTimer
{
    [self doSomething:nil];

    float theTime = 20; // This is the time interval.

    if(keepOn)
    {
        [self performSelector:@selector(fireTimer) withObject:nil afterDelay:theTime];
    }
}

(非常)bis问题是,“计时器”正在等待整个延迟,然后才能获得新值。 你看,它没有快速响应:)) 你不能立即停止它(必须等待延迟完成)。

如果你停止它,它会再投掷一个动作。

实际上它适用于我,对于小应用程序和工具都没问题。

答案 1 :(得分:0)

您不应该发布mainLoopTimer 当您创建它时,您收到了一个自动释放的实例,并且runloop保留了对该实例的引用 当它从循环中删除时它将被释放:如果您手动释放它,它将被删除,并且runloop会尝试访问无效的对象。
这就是崩溃的原因。

编辑: 我完全误读了,我以为我看到释放时它是无效的,对不起。 问题似乎是没有AutoreleasePool。 这通常在main()中完成:创建自动释放池作为第一件事

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

并在退出main之前将其释放。

查看自动发布池文档的here

答案 2 :(得分:-2)

您可以尝试取消注册前一个计时器并启动不同频率的新计时器。 你可以通过

取消注册
[yourOldTimer invalidate];
yourOldTimer = nil;

这可能会解决目的。