2013-06-01 62 views
0

我正在爲Mac OS X中的CLI工具,我的主要看起來是這樣的:的NSTimer/NSRunLoop發出

int main(int argc, const char * argv[]){ 

    @autoreleasepool { 

     //Some startup stuff here 
     [ServerPool sharedPool]; //Start the pool 

     /* 
     UI stuff for cli version 
     */ 
     while (1){ 
      [[CLIUI sharedCLI] mainMenu]; 
      [[CLIUI sharedCLI] menuInput]; 
     } 

    } 
    return 0; 
} 

,並在代碼中的另一段我開始的NSTimer

progressUpdateTimer = [NSTimer timerWithTimeInterval:1.0 
               target:self 
              selector:@selector(updateProgress:) 
              userInfo:nil 
              repeats:YES]; 

[[NSRunLoop currentRunLoop] addTimer: progressUpdateTimer forMode:NSDefaultRunLoopMode]; 

但是,它永遠不會觸發選擇器updateProgress :.我相信這是因爲我沒有在我的主體中建立一個NSRunLoop,那麼適當的解決方法是什麼?

+0

您的'mainMenu'和'menuInput'方法是否阻塞,直到發生某些事件?或者他們是否只是輪詢一個事件並立即返回?如果他們阻止,他們阻止什麼? –

+0

fgets(_input,sizeof _input,stdin); ... –

+0

我想讓主菜單和後臺線程輸入不是嗎? –

回答

1

除非運行循環運行,否則定時器和其他依賴於運行循環的內容不會觸發。

在一個命令行程序,你會理想地使用dispatch_main()和控制傳遞給GCD 運行在合適的模式下[NSThread currentRunLoop]的時間適當的量。

你將不得不擺脫while(1),因爲它會阻止運行循環。

concurrent programming documentation有關於如何使用運行循環的大量文檔。

如果你確實需要while循環,將它移動到第二個線程(主線程上的NSRunLoop更容易處理)並在主線程上運行運行循環。


您需要用一個NSRunLoop代替while(1)循環。這也可能意味着您需要將輸入代碼更改爲dispatch_source或從stdin等讀取的NSFileHandle ...

也就是說,你將不得不重構你的代碼很多。做一個谷歌搜索的東西,如「在命令行程序中使用nsrunloop」,你可能會得到不少提示。另外,NSRunLoop文檔指向了一堆示例。

它看起來令人生畏,但一旦你開始注意NSRunLoops,它們是非常強大的構造。

+0

你能在這裏詳細說明嗎?我完全不知道如何(或在哪裏)我的主循環應該/去... –

+0

我已經切換到這個:https://gist.github.com/RyanCopley/829d33bb328651b1fb1b 一切似乎工作,除了定時器仍然沒有開火。 –

+0

你的'sharedCLI'方法是做什麼的?如果阻塞,等待輸入,那麼定時器將不會觸發(這就是爲什麼您要移動到NSFileHandle或將現有I/O從主線程移出)。 – bbum