2011-01-07 20 views
1

由於某些原因,當我按下(單擊並按住)任何控件時,我的應用程序中的NSTimer凍結,直到釋放鼠標按鍵纔會觸發。當我按下鼠標時,它不會觸發。這很短時間,但它也凍結,如果我有一個彈出菜單打開,或組合框下降。NSRunLoop因NSTimer和任何輸入而凍結

我不確定是否有一些我錯過了,但它似乎是不正確的行爲。

我希望能夠單擊NSPopUpButtonCell的向下箭頭(或者甚至單擊並按住NSTableView),而不會讓整個NSTimer凍結(重繪NSView)。

任何意見/建議,將不勝感激。

NSTimer以模式NSDefaultRunLoopMode添加到currentRunLoop。

回答

8

鼠標關閉時,運行循環位於NSEventTrackingRunLoopMode。因此,任何事件而不是收到EventTracking事件隊列將不會服務,直到runloop返回到適當的模式。

解決方法是將兩個模式(默認和事件跟蹤)的計時器添加到runloop中。

0

假設你只是在處理應用程序中的一個線程,你所描述的是完美的預期。默認情況下,NSTimer被添加到當前的NSRunLoop,在您的情況下,它也負責處理UI交互。當它處理UI交互時,它不能檢查你的計時器並「啓動」它。

A解決方案是使用多線程,以避免這種聯繫。下面是關於這個主題一個很好的博客文章:http://blog.narent.com/?p=21

編輯:見戴夫的職位替代(和更優雅IMO)解決方案

另見:

+0

多線程肯定是* a *解決方案,但它不是唯一的解決方案。 – 2011-01-07 05:53:32

+0

感謝您的更正,知道的好東西。你的解決方案看起來好多了! – Sam 2011-01-07 06:00:08

+0

謝謝。在第二個線程上運行定時器是一個不錯的選擇。 *不*這樣做的主要原因是,如果您使用計時器觸發UI更新,因爲您不應該更新除主線程以外的其他任何UI,而這個人顯然是使用它(儘管您我可以回到主線程......)。 – 2011-01-07 06:18:00

8

而是將兩個或多個定時器不同runloops或使用多線程(因爲你不會再能夠更新從另一個線程的UI)只是將計時器添加到NSRunLoopCommonModes的:

NSTimer *myTimer = [NSTimer timerWithTimeInterval:RefreshInterval target:self selector:@selector(doWork) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes];