Cocoa应用程序有一个主循环吗?

won*_*rer 1 cocoa runloop

在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;
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试为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];
   }

}
Run Code Online (Sandbox Code Playgroud)

这似乎不太好用.计时器一直处于关闭状态.我也试过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.
Run Code Online (Sandbox Code Playgroud)

编辑2

好,我知道了.问题是我没有向计时器添加"目标:".现在,当我关闭计时器时,我收到以下错误:

MouseClick(1652) malloc: * error for object 0x1645c0: double free * set a breakpoint in malloc_error_break to debug 
Run Code Online (Sandbox Code Playgroud)

计时器的释放如下:

[timer invalidate]; 
[timer release]; 
timer = nil;
Run Code Online (Sandbox Code Playgroud)

zou*_*oul 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];
Run Code Online (Sandbox Code Playgroud)

现在该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];
}
Run Code Online (Sandbox Code Playgroud)

当然现在你有线程,这意味着同步和比计时器更令人头痛.正如我所说,这取决于你想做什么.

并回答你原来的问题:是的,Cocoa应用程序确实有一个"主循环",可能与GTK类似.由于已经为您创建了循环,因此编写另一个循环是没有意义的 - 除非您试图弄清楚事情是如何工作的或做一些复杂的事情.有关详细信息,请参阅线程编程指南中的运行循环管理

如果您只想处理事件,默认的运行循环将为您完成.只需实现处理程序,即.连接到按钮和这些东西的方法.如果您想定期执行某些操作(例如更新动画等),请设置计时器(NSTimer).默认的运行循环将处理时间,它将根据需要经常调用适当的选择器.