2012-08-14 52 views
0

我注意到在我的程序中,当我调用NSRunAlertPanel()时,它等待返回(用户还没有点击一个按钮),NSTimer()不会触发。它会定期触发,直到NSRunAlertPanel()行完成,但直到用户单击对话框上的按钮时才会再次调用。NSRunAlertPanel暂停NSTimer?

即使对话框在屏幕上,是否有一种方法可以保持定时器运行?

回答

1

警报面板正在启动自己的事件循环(通过-[NSApplication runModalForWindow:],与计时器最初预定的事件循环(大概是main)分开),以防止用户与应用程序的任何其他元素进行交互,直到处理警报

关闭我的头顶,有两种方式可以让面板显示时计时器仍然闪烁:运行主运行循环,并将计时器添加到面板的运行中我真的不知道这两者中的任何一个会如何工作

首先,您可以很容易地获得应用程序的主运行循环:[NSRunLoop mainRunLoop]和然后在runUntilDate:短时间内(不到一秒)告诉它。这将要求您设置一个(while)循环,让主运行循环和模态运行循环交替运行一段时间。这里的问题是让主运行循环处于活动状态将允许处理输入,从而破坏面板的模态。

对于第二个,你只需参考计时器,然后做[[NSRunLoop currentRunLoop] addTimer:forMode:]。我不确定的是计时器的启动日期将如何与重新添加到另一个循环进行交互,但您可以尝试一下。

希望我是一个白痴,错过了一些非常明显的东西,另一个答案很快就会出现,并带有正确的解决方案。

+0

感谢您的建议!你的第二个选择给了我一个很好的开始,所以我可以研究它 - 它似乎通常被推荐为一种解决方案,但由于找不到完整的示例代码,我有点困惑。我编辑了我的问题以包含帮助他人的解决方案。 – 2012-08-15 16:38:53

+1

很高兴有帮助。你应该感到自由(事实上,它[最好]](http://meta.stackexchange.com/questions/17463/can-i-answer-my-own-questions-even-those-where-i-knew答案之前问?lq = 1))把你的解决方案放入一个答案(甚至标记为接受的答案,如果你想)。 – 2012-08-15 16:41:22

1

感谢W'rkncacnter的建议!下面是我的解决方案的消毒版本。

当把我的计时器在屏幕上,我使用:

timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateTimer) userInfo:nil repeats:YES]; 

这就需要下面的代码每秒:

- (void) updateTimer { 
    secondsRemaining--; 
    if (secondsRemaining <= 0) { 
     [timer invalidate]; 
     [[NSApplication sharedApplication] abortModal]; 
     [self finishStuff]; 
    } 

    [self updateTimerText]; 
} 

- (void) updateTimerText { 
    NSInteger seconds = (int) secondsRemaining; 
    NSInteger hours = seconds/(60 * 60); 
    seconds -= hours * (60 * 60); 
    NSInteger minutes = seconds/60; 
    seconds -= minutes * 60; 

    [timerText setStringValue:[NSString stringWithFormat:@"%02ld:%02ld:%02ld", hours, minutes, seconds]]; 
} 

注意 “abortModal” 代码。如果在定时器耗尽时NSRunAlertPanel()被打开,它将被关闭。 当我想显示对话框,运行此代码:

[[NSRunLoop currentRunLoop] addTimer:timer 
          forMode:NSModalPanelRunLoopMode]; 
NSInteger buttonClicked = NSRunAlertPanel(@"Finish?", @"Are you sure you are done?", @"No", @"Yes", nil); 

//"YES" clicked 
if (buttonClicked == NSAlertAlternateReturn) { 
    [timer invalidate]; 
    [self finishStuff]; 
} 

注意,我又增加计时器,这个时候不同的运行循环 - 模态窗口。计时器仍处于原始运行循环,并在对话框关闭时继续。