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でコマンドラインシェルウィンドウで何かを実行する方法のようなものであり、プロセスが終了すると、「続行するにはQキーを押してください.. .」。ウィンドウを前面に移動して (まだ最前面にない場合)、Q キーを押すと、ウィンドウが閉じます。

このコマンド ライン ツールをプライマリ アプリケーションから呼び出す予定ですか、それともエンド ユーザーが直接操作するコマンド ライン ツールですか? (たとえば、後者の場合、ターミナル ウィンドウから呼び出す場合、うーん、Ken のコードを私のコードと組み合わせて次のようにすることができると思います。現在の形式では、これは を押した後にのみ機能することに注意してください。 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;
}
于 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 に答える