0

我正在 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;
}

谢谢!

4

3 回答 3

3

我自己没有这样做,但我希望您想使用[[NSFileHandle fileHandleWithStandardInput] readInBackgroundAndNotify]并注册以接收NSFileHandleReadCompletionNotification通知。如果您收到“q”,请执行您需要做的任何清理工作并调用exit().

于 2011-01-06T01:35:47.917 回答
0

好吧,我从您现有代码开始的最初理论和实验并没有以可用代码的方式出现。

我想象你正在寻找的东西就像在 Windows 上,你可以在命令行 shell 窗口中运行某些东西,当进程完成后,它会显示类似“按 Q 键继续.. ."。当您将窗口向前(如果它还不是最前面)并按 Q 键时,窗口将关闭。

您是打算从您的主应用程序中调用此命令行工具,还是最终用户将直接与此命令行工具交互?(例如,如果是后者,他们会从终端窗口调用它,嗯,那么我认为 Ken 的代码可能会与我的代码结合起来进行以下操作。请注意,在其当前形式中,这仅在您按下后才有效Q然后按回车?

#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;
}
于 2011-01-06T09:34:10.453 回答
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()每次运行循环结束时调用。

于 2011-01-06T12:09:54.337 回答