Остановить NSRunLoop при нажатии клавиш - PullRequest
0 голосов
/ 06 января 2011

Я пишу инструмент для командной строки в Mac OS X и хотел бы, чтобы этот инструмент завершился нажатием клавиши, например 'q' Код запускает асинхронный запрос на получение данных с удаленного сервера. Это требует NSRunLoop. По крайней мере, это то, что я понимаю, мне нужно сделать.

Может кто-нибудь сказать мне, как остановить цикл запуска на определенное нажатие клавиши?

Ниже приведен фрагмент кода.

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

BOOL keepRunning = YES;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

Requestor *myRequestor = [[Requestor alloc] init];
[myRequestor GetData];

NSRunLoop *runLoop;
runLoop = [NSRunLoop currentRunLoop];

while (keepRunning && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);

[pool drain];
return 0;
}

Спасибо!

Ответы [ 3 ]

3 голосов
/ 06 января 2011

Я сам этого не делал, но я ожидаю, что вы захотите использовать [[NSFileHandle fileHandleWithStandardInput] readInBackgroundAndNotify] и зарегистрируйтесь, чтобы получить уведомление NSFileHandleReadCompletionNotification. Если вы получили 'q', сделайте все, что вам нужно, и позвоните exit().

0 голосов
/ 06 января 2011

Если вы еще не рассматривали libcurses , возможно, это вам поможет.Это действительно просто - поймать нажатие клавиш, но я не уверен на 100%, если вы можете заставить его работать без использования всего окна терминала.

#include <ncurses.h>

initscr();

/* snip */

char c;
while (c = getch()) {
  if (c == 'q') {
    // Put your cleanup and shutdown logic here
  }

  /* any other keypresses you might want to handle */
}

РЕДАКТИРОВАТЬ |Вы, вероятно, не хотите помещать этот тугой цикл в цикл выполнения ... просто вызывайте getch() каждый раз, когда цикл запускается.

0 голосов
/ 06 января 2011

Что ж, мои первоначальные теории и эксперименты, начиная с вашего существующего кода, не сильно повлияли на использование кода.

Мне кажется, что вы ищете что-то вроде того, как в Windows вы можете запустить что-то в окне командной строки, а когда процесс завершится, он скажет что-то вроде: «Нажмите клавишу Q, чтобы Продолжить...". Когда вы выдвигаете окно вперед (если оно уже не переднее) и нажимаете клавишу Q, окно закрывается.

Планируете ли вы вызывать этот инструмент командной строки из основного приложения или этот инструмент командной строки будет взаимодействовать с конечным пользователем напрямую? (Например, если последние, они будут вызывать его из окна терминала, хм, тогда я думаю, что код Кена, вероятно, можно было бы объединить с моим, чтобы сделать следующее. Обратите внимание, что в его текущей форме это работает только после того, как вы нажмете Q и затем нажмите Return?

#import <Cocoa/Cocoa.h>

@interface Requestor : NSObject <NSApplicationDelegate> {
    BOOL            gotData;
    NSFileHandle    *stdIn;
}
- (void)getData;
- (void)requestorGotData:(id)sender;
@end

@implementation Requestor

- (id)init {
    if (self = [super init]) {
        gotData = NO;
        stdIn = nil;
        [NSApp setDelegate:self];
    }
    return self;
}

- (void)getData {
    NSLog(@"getting data.........");
    gotData = NO;

    [self performSelector:@selector(requestorGotData:)
               withObject:nil
               afterDelay:5.0];
}

перерыв

- (void)requestorGotData:(id)sender {
    NSLog(@"got data");
    gotData = YES;
    NSLog(@"Press 'Q' key to continue...");
    stdIn = [[NSFileHandle fileHandleWithStandardInput] retain];
    [[NSNotificationCenter defaultCenter]
       addObserver:self
          selector:@selector(fileHandleReadCompletion:)
              name:NSFileHandleReadCompletionNotification
            object:stdIn];
    [stdIn readInBackgroundAndNotify];
}

- (void)fileHandleReadCompletion:(NSNotification *)notification {
    NSLog(@"fileHandleReadCompletion:");
    NSData *data = [[notification userInfo]
                    objectForKey:NSFileHandleNotificationDataItem];
    NSLog(@"data == %@", data);
    NSString *string = [[[NSString alloc]
                             initWithData:data
                        encoding:NSUTF8StringEncoding] autorelease];
    if (string) {
        string = [string stringByTrimmingCharactersInSet:
                  [NSCharacterSet whitespaceAndNewlineCharacterSet]];
        if ([[string lowercaseString] isEqualToString:@"q"]) {
            [stdIn closeFile];
            [stdIn release];
            [[NSNotificationCenter defaultCenter] removeObserver:self];
            [NSApp terminate:nil];
        } else {
            [stdIn readInBackgroundAndNotify];
        }
    }
}
@end

перерыв

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    [NSApplication sharedApplication];

    Requestor *requestor = [[Requestor alloc] init];
    [requestor getData];

    [NSApp run];

    [requestor release];

    [pool drain];
    return 0;
}
...