2010-07-19 31 views
0

我正在爲GUI(可可)提供一個命令行工具,以使其更易於人們訪問。儘管它是一個GUI,但我想將輸出顯示到NSTextView。問題是輸出量很大,工具執行的分析可能需要幾小時/天。如何逐步從NSTask中檢索數據?

正常情況下,使用NSTask和NSPipe時,只有在任務完成後(可能需要很長時間)才顯示輸出。我想要做的是將輸出分開並逐漸顯示(例如每分鐘更新一次)。

到目前爲止,我已經放在了數據的處理在一個單獨的線程:

[NSThread detachNewThreadSelector:@selector(processData:) toTarget:self withObject:raxmlHandle]; 

- (void)processData:(id)sender { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSString *startString = [results string]; 
    NSString *newString = [[NSString alloc] initWithData:[raxmlHandle readDataToEndOfFile] encoding:NSASCIIStringEncoding]; 
    [results setString:[startString stringByAppendingString:newString]]; 
    [startString release]; 
    [newString release]; 
    [pool release]; 
} 

這一切還是有點巫術給我的,我不完全知道如何應對這一挑戰。

您有什麼建議或建議嗎?

謝謝!

回答

3

您需要使用NSFileHandle提供的通知。

首先,作爲觀察員將自己添加到NSFileHandleReadCompletionNotification

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(outputReceived:) 
              name:NSFileHandleReadCompletionNotification 
              object:nil]; 

然後,準備一個任務,叫管的文件句柄readInBackgrounAndNotify,並啓動任務。

NSTask*task=[[NSTask alloc] init]; 
[task setLaunchPath:...]; 

NSPipe*pipe=[NSPipe pipe]; 
[task setStandardOutput:pipe]; 
[task setStandardError:pipe]; 

// this causes the notification to be fired when the data is available 
[[pipe fileHandleForReading] readInBackgroundAndNotify]; 

[task launch]; 

現在,實際接收到的數據,您需要定義一個方法

-(void)outputReceived:(NSNotification*)notification{ 
    NSFileHandle*fh=[notification object]; 
    // it might be good to check that this file handle is the one you want to read 
    ... 

    NSData*d=[[aNotification userInfo] objectForKey:@"NSFileHandleNotificationDataItem"]; 
    ... do something with data ... 
} 

您可能需要閱讀Notification Programming Topics明白是怎麼回事。

+0

非常感謝Yuji,花時間寫下你的答案。我會馬上潛入! – 2010-07-20 06:11:45

+1

有誰知道如何更好地控制NSPipe的輸出大小?換句話說,通過上述方法(Yuji的方法),數據被大塊清除,這使得用戶不太友好。我正在尋找一種解決方案,可以單獨顯示每行輸出(更像終端或控制檯工作)。有什麼建議麼? – 2010-07-20 17:46:57

+0

閱讀此SO討論:http://stackoverflow.com/questions/1000674/turn-off-buffering-in-pipe問題是,當發送數據到管道時,發送端的stdio會自動更改其行爲。你需要欺騙它認爲它寫入了一個tty。應該有一種方法來在Cocoa中實現tty,但我不知道如何。我確信它可以在iTerm的源代碼http://iterm.sourceforge.net/中找到。 – Yuji 2010-07-20 18:24:47