如何在仍允许用户输入控制台的同时运行NSTimer?

时间:2014-01-10 22:08:02

标签: objective-c grand-central-dispatch nstimer objective-c++ nsrunloop

长话短说,我正在尝试创建一个简单的控制台游戏,允许用户将命令输入控制台以执行操作(例如启动/停止),同时打印出各种属性和操作进入控制台。

    _gameDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(_gameDispatchQueue, ^{
                       _propertyTimer=[NSTimer scheduledTimerWithTimeInterval: 0.1
                                               target: mairne
                                               selector: @selector(printProperties:)
                                               userInfo: nil
                                               repeats: YES];
                       [[NSRunLoop currentRunLoop] run];
                   });

在我的main.mm文件中,我通过cin接受输入,然后在输入时接受输入。

我对这段代码的问题在于,尽管我试图将它放在后台线程中,但它仍然不允许用户输入任何内容并按Enter键。因此,例如,如果他们想要编写stop并按Enter键,则不会处理该命令。

如何让NSTimer在后台打印时运行,但仍允许处理用户输入?

4 个答案:

答案 0 :(得分:2)

尝试在主线程上运行计时器但在选择器printProperties中运行,让它在调度队列中运行所有内容,如下所示:

// Init these somewhere on the main thread
_bgQueue = dispatch_queue_create("com.yourco.yourapp.bgQueue", NULL);
_propertyTimer=[NSTimer scheduledTimerWithTimeInterval: 0.1
                                               target: mairne
                                               selector: @selector(printProperties:)
                                               userInfo: nil
                                               repeats: YES];

- (void)printProperties:(id)sender
{
   dispatch_async(_bgQueue, ^{
      // do your work here
   }
}

答案 1 :(得分:1)

为了进一步扩展bbum的答案,NSFileHandle实际上有一个很好的Objective-C API,用于设置dispatch_source

您可以像NSFileHandle一样获得stdin

 NSFileHandle *standardInputHandle = [NSFileHandle fileHandleWithStandardInput];

NSFileHandle有一个名为readabilityHandler的属性,它会在数据进入时调用(异步)块。所以,你可以这样做:

standardInputHandle.readabilityHandler = ^(NSFileHandle *fileHandle) { handleUserInputData([fileHandle availableData]); };

假设您可以/想要逐行处理传入数据(即返回/换行始终是命令的结尾),这可能会对您有效。

答案 2 :(得分:1)

尝试将ncurses用于此类控制台应用程序是值得的。 getch nodelay用作非阻止键输入。

 void initialize_function() {
     nodelay(stdscr, TRUE);
 }

 void function_will_be_called_from_NSRunLoop() {
      int ch;
      if ((ch = getch()) != ERR) {
          /*
           * user has pressed a key ch, pool it into a queue for parsing command
           * like start, stop, or something like that
           */
      }

      /*
       * print out various properties and actions into the ncurses screen (the console)
       */
 }

答案 3 :(得分:0)

将读数从stdin移开主线程。或者,可能使用附加到dispatch_source文件句柄的stdin在数据可用时提供回调(缓冲可能很棘手)。