在Linux下X11并使用GTK +,你会有一个叫做“主循环”的东西。一旦启动主循环,就会有一个在应用程序主线程中运行的计时器。您可以将该计时器设置为回调函数,并且您有一个非常好的应用程序范围的计时器。
这是示例代码:
GMainLoop *loop;
if(!loop_running)
{
display = XOpenDisplay( NULL );
loop = g_main_loop_new(NULL, FALSE);
g_timeout_add(1000, (GSourceFunc)callback, NULL); //1 sec laps
g_main_loop_run(loop); //to stop use g_main_loop_quit () with the "loop" as arg
loop_running=1;
}
我正在尝试为Mac OS X编写类似的应用程序,而不是主循环我正在使用一个简单的计时器:
- (void) handleTimer: (NSTimer *) timer
{
CopyDataToDB();
} // handleTimer
- (IBAction)startStopAction:(id)sender
{
isOn=!isOn;
if(isOn)
{
// Add our timers to the EventTracking loop
[[NSRunLoop currentRunLoop] addTimer: time forMode: NSEventTrackingRunLoopMode];
// Add our timers to the ModelPanel loop
[[NSRunLoop currentRunLoop] addTimer: time forMode: NSModalPanelRunLoopMode];
}
else
{
[timer invalidate];
}
}
这似乎不太好用。计时器一直处于关闭状态。我也试过NSTimer,但没有运气。 我不熟悉objective-c,特别是GUI应用程序。
无论如何,任何想法如何在Cocoa上实现应用程序范围的计时器(objective-c with Xcode)?
谢谢!
修改 使用NSTimer时,这是我在运行时得到的错误:
**[Session started at 2009-07-12 16:49:59 -0400.]
2009-07-12 16:50:02.784 MouseClick[1490:10b] Starting
2009-07-12 16:50:02.786 MouseClick[1490:10b] *** +[NSTimer scheduledTimerWithTimeInterval:selector:userInfo:repeats:]: unrecognized selector sent to class 0xa08d54c0
2009-07-12 16:50:02.787 MouseClick[1490:10b] *** +[NSTimer scheduledTimerWithTimeInterval:selector:userInfo:repeats:]: unrecognized selector sent to class 0xa08d54c0**
The Debugger has exited with status 0.
编辑2
好的,我明白了。问题是我没有向计时器添加“目标:”。现在,当我关闭计时器时,我收到以下错误:MouseClick(1652) malloc: * error for object 0x1645c0: double free * set a breakpoint in malloc_error_break to debug
计时器的释放完成如下:
[timer invalidate];
[timer release];
timer = nil;
答案 0 :(得分:7)
取决于你究竟想做什么。大多数情况下,你不应该乱用运行循环,只需设置一个计时器:
const float framerate = 40;
const float frequency = 1.0f/framerate;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:frequency
target:self selector:@selector(doSomething)
userInfo:nil repeats:YES];
现在doSomething
方法每秒执行约40次。如果你想尽可能频繁地执行某些事情,你可以产生一个新线程:
- (void) loop
{
while (running)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Do something useful.
[pool release];
}
}
- (void) run
{
run = YES;
[NSThread detachNewThreadSelector:@selector(loop)
toTarget:self withObject:nil];
}
当然现在你有了线程,这意味着同步和比计时器更令人头疼的问题。正如我所说,这取决于你想做什么。
回答你原来的问题:是的,Cocoa应用程序确实有一个“主循环”,可能与GTK类似。由于已经为您创建了循环,因此编写另一个循环是没有意义的 - 除非您试图弄清楚事情是如何工作的或做一些复杂的事情。有关详细信息,请参阅“线程编程指南”中的Run Loop Management。
如果您只想处理事件,默认的运行循环将为您完成。只需实现处理程序,即。连接到按钮和这些东西的方法。如果您想定期执行某些操作(例如更新动画等),请设置计时器(NSTimer
)。默认的运行循环将处理时间,它将根据需要经常调用适当的选择器。
答案 1 :(得分:1)
可以设置任何对象作为其目标的计时器;并且有许多合适的入口点可以将计时器“附加”到所需目标。
我不太确定在这种情况下你从哪里得到time
;但我猜它是用+timerWithTimeInterval:invocation:repeats:
创建的计时器(在NSTimer上)或许?如果没有,该特定方法应该为您提供一个非常有用的计时器供您使用。
答案 2 :(得分:0)
尝试NSTimer时,你是否保留了计时器?如何保留计时器调用的对象......