我在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间隔的任何想法吗?
谢谢!
答案 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;
这可能会解决目的。