【问题标题】:Do Cocoa applications have a main loop?Cocoa 应用程序有主循环吗?
【发布时间】:2009-07-12 20:16:03
【问题描述】:

在 X11 下的 Linux 上并使用 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;

【问题讨论】:

    标签: cocoa runloop


    【解决方案1】:

    取决于您到底想做什么。大多数时候你不应该弄乱运行循环,只需设置一个计时器:

    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)。默认的运行循环会处理好时间,它会根据需要调用适当的选择器。

    【讨论】:

    • 好的,我尝试了类似的方法,但我遇到了很多错误。这是代码(抱歉没有格式化它不允许我在评论中格式化它): timer = [NSTimer scheduledTimerWithTimeInterval: 0.5 selector: @selector(handleTimer:) userInfo: nil repeats: YES];
    • 这应该可以。您能否将代码和您遇到的错误添加到问题中?
    • 好的,我明白了。问题是我没有向计时器添加“目标:”。现在,当我关闭定时器时,出现以下错误: MouseClick(1652) malloc: *** error for object 0x1645c0: double free *** set a breakpoint in malloc_error_break to debug 定时器的释放完成如下:[定时器无效]; [定时器释放];计时器 = nil;
    • 只需发送“无效”消息并忽略“释放”。正在运行的计时器不是手动释放的,您调用“无效”,运行循环将在一段时间后释放计时器。 (请参阅 NSTimer 文档。)
    • 谢谢!我将尝试使用计时器将所有功能打包到这个文件中。希望这会奏效。
    【解决方案2】:

    可以设置一个计时器,将任何对象作为它的目标;并且有许多合适的入口点可以将计时器“附加”到所需的目标。

    我不太确定在这种情况下你从哪里得到time;但我猜它可能是用+timerWithTimeInterval:invocation:repeats:(在NSTimer 上)创建的计时器?如果没有,该特定方法应该为您提供一个非常有用的计时器供您使用。

    【讨论】:

      【解决方案3】:

      在尝试 NSTimer 时,您是否保留了计时器?保留计时器调用的对象怎么样...

      【讨论】:

      • 计时器被运行循环保留,你不必自己做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      相关资源
      最近更新 更多