Остановить NSRunLoop при нажатии клавиш
Я пишу основную утилиту командной строки в Mac OS X и хотел бы, чтобы инструмент завершился нажатием клавиши, такой как 'q'. Код запускает асинхронный запрос на получение данных с удаленного сервера. Это требует NSRunLoop. По крайней мере, это то, что я понимаю, мне нужно сделать.
Может кто-нибудь сказать мне, как остановить runloop на конкретном нажатии клавиши?
Ниже приведен фрагмент кода.
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 ответа
Я не сделал этого сам, но я ожидаю, что вы хотите использовать [[NSFileHandle fileHandleWithStandardInput] readInBackgroundAndNotify]
и зарегистрируйтесь, чтобы получить NSFileHandleReadCompletionNotification
уведомление. Если вы получили 'q', сделайте все, что вам нужно, и позвоните exit()
,
Ну, мои первоначальные теории и эксперименты, начиная с вашего существующего кода, не сильно повлияли на использование кода.
Я представляю, что вы ищете что-то вроде того, как в 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;
}
Если вы еще не рассматривали 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()
каждый раз, когда рулетка тикает.