0

Короче говоря, я пытаюсь создать простую консольную игру, которая позволяет пользователю вводить команды в консоль, чтобы выполнять действия (например, запуск/останов), в то же время распечатывая различные свойства и действия в консоль.Как я могу запустить NSTimer, сохраняя при этом консольный ввод от пользователя?

_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 работать в фоновом режиме, но все же разрешить обработку ввода пользователем?

ответ

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 
    } 
} 
+0

Как вы можете видеть, когда цель различна, printProperties находится в другом классе, чем при создании '_propertyTimer'. Как printProperties знает об _bgQueue? –

+0

А хорошая точка. в этом случае цель должна быть «я», предполагая, что _bgQueue и _propertyTimer инициализируются в (id) init – valheru

0

Переместить показание от stdin от основной темы. Или, возможно, используйте dispatch_source, прикрепленный к дескриптору файла stdin, чтобы обеспечить обратный вызов, когда доступны данные (буферизация может быть сложной).

+0

Как бы идти о переходе 'stdin' от основного потока? –

+0

Выполняя операции ввода-вывода только на 'stdin' в каком-то другом потоке/очереди. Или используйте решение, которое рекомендует Кадзуки. – bbum

+0

Например, принимал бы вход в 'stdin' через работу очереди' dispatch_async'? –

1

Чтобы несколько расширить ответ bbum, в NSFileHandle на самом деле имеет хороший Objective-C API, который завершает настройку dispatch_source.

Вы можете получить NSFileHandle для stdin так:

NSFileHandle *standardInputHandle = [NSFileHandle fileHandleWithStandardInput]; 

NSFileHandle имеет свойство readabilityHandler, принимающий блок будет называться (асинхронно), когда данные поступают в Таким образом, вы можете сделать что-то вроде этого. :

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

Предполагая, что вы можете/хотите обрабатывать входящие линии передачи данных по линии (т. е возвращение/новая строка всегда конец команды), это вероятно, будет работать для вас, как есть.

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) 
     */ 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^