1

在 XCode 3.1.1 中为 OSX 10.5.8 目标、32 位和 i386 构建编译。

我有一个模态运行循环,在 NSWindow wloop 和 NSView vloop 中运行。模态循环首先启动。它按预期启动、运行和停止。这是开始:

[NSApp runModalForWindow: wloop];

然后,当用户按下鼠标左键时,我这样做:

if (ticking == 0) // ticking is set to zero in its definition, so starts that way
{
    ticking = 1; // don't want to do this more than once per loop
    tickCounter = 0;
    cuckCoo = [NSTimer scheduledTimerWithTimeInterval: 1.0f / 10.0f         // 10x per second
                                               target: self                 // method is here in masterView
                                             selector: @selector(onTick:)   // method
                                             userInfo: nil                  // not used
                                              repeats: YES];                // should repeat
}

检查调用的返回,我确实得到了一个定时器对象,并且可以确认定时器调用是在我期望的时候进行的。

现在,根据文档,全局存储为“cuckCoo”的生成的 NSTimer 应该自动添加到当前的运行循环中。当前的运行循环绝对是模态的——此时其他窗口被锁定,只有具有预期鼠标操作的窗口正在接收消息。

它调用的方法“onTick”非常简单(因为我无法启动它),位于 vloop NSView 代码中,这就是所有这些发生的地方:

- (void) onTick:(NSTimer*)theTimer
{
    tickCounter += 1;
    NSLog(@"Timer started");
}

然后,当需要停止模态循环(工作正常,顺便说一句)时,我这样做:

[cuckCoo invalidate];
[NSApp stop: nil];
ticking=0;
cuckCoo = NULL;
NSLog(@"tickCounter=%ld",tickCounter);

ticking 和 tickCounter 都是全局多头。

我没有从 onTick 中收到 NSLog 消息,并且 tickCounter 在运行循环结束时由 NSLog 报告保持为零。

所有这些都可以编译并运行良好。我只是从来没有得到任何蜱虫。我完全不知所措。任何想法,任何人?

4

2 回答 2

3

问题与“当前运行循环绝对是模态循环”这句话有关。在 Cocoa 中,每个线程最多有一个 runloop,每个 runloop 都可以以多种“模式”运行。典型的模式是默认、事件跟踪和模态。默认是循环正常运行的模式,而事件跟踪通常用于跟踪鼠标的拖动会话,而模式用于模式面板之类的东西。

当您调用 -[NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:] 时,它会立即安排计时器,但它仅将其安排为默认运行循环模式,而不是模式运行循环模式。这背后的想法是应用程序通常不应该继续在模式面板后面运行。

要创建在模态运行循环期间触发的计时器,您可以使用 -[NSTimer initWithFireDate:interval:target:selector:userInfo:repeats:] 然后 -[NSRunLoop addTimer:forMode:]。

于 2011-03-22T18:43:19.010 回答
1

具体答案...

[NSApp runModalForWindow: wloop];

...是,在进入模态运行循环之后:

NSRunLoop *crl;

    cuckCoo = [NSTimer timerWithTimeInterval: 1.0 / 10
                                      target: self
                                    selector: @selector(onTick:)
                                    userInfo: nil
                                     repeats:YES];
    crl = [NSRunLoop currentRunLoop];
    [crl addTimer: cuckCoo forMode: NSModalPanelRunLoopMode];

(为清楚起见,crl 单独获得)其中 onTick 方法具有以下形式:

- (void) onTick:(NSTimer*)theTimer
{
    // do something tick-tocky
}
于 2011-03-22T21:05:50.070 回答