2012-08-14 51 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]; 
} 

注意,我又增加計時器,這個時候不同的運行循環 - 模態窗口。計時器仍處於原始運行循環,並在對話框關閉時繼續。