2010-03-09 53 views
5

嗨:我想將stdout重定向到NSTextView。這也可以用於子流程的輸出嗎?什麼可能是實現這一目標的最佳途徑?在可可中將stdout重定向到NSTextView的最佳方式是什麼?

編輯: 根據彼得Hosey答案我執行以下。但我沒有收到通知。我究竟做錯了什麼?

NSPipe *pipe = [NSPipe pipe]; 
NSFileHandle *pipeHandle = [pipe fileHandleForWriting]; 
dup2(STDOUT_FILENO, [pipeHandle fileDescriptor]); 
NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:pipeHandle]; 
[fileHandle acceptConnectionInBackgroundAndNotify]; 

NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; 
[dnc addObserver:self selector:@selector(handleNotification:) name:NSFileHandleConnectionAcceptedNotification object:fileHandle]; 
+0

python與此有什麼關係? – Eimantas 2010-03-09 08:52:55

+0

@Eimantas:你說得對,它與問題沒有直接關係。其實我正在使用PyObj與Python代碼寫入** stdout **,我想要顯示。我應該刪除標籤... – Sney 2010-03-09 09:12:52

回答

12

我期待着做同樣的事情,並遇到這個職位。在閱讀完本文和Apple的文檔後,我能夠弄明白。我在這裏包括我的解決方案。在接口中聲明「pipe」和「pipeReadHandle」。在init方法中我包括下面的代碼:

pipe = [NSPipe pipe] ; 
pipeReadHandle = [pipe fileHandleForReading] ; 
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stdout)) ; 

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleNotification:) name: NSFileHandleReadCompletionNotification object: pipeReadHandle] ; 
[pipeReadHandle readInBackgroundAndNotify] ; 

的的handleNotification:方法是

[pipeReadHandle readInBackgroundAndNotify] ; 
NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ; 
// Do whatever you want with str 
+0

這對我有很大的幫助。謝謝!我用你的建議,並添加這兩個消息,使textView增長和autoscroll使用以下:[myTextView setText:[myTextView.text stringByAppendingString:str]]; [myTextView scrollRangeToVisible:NSMakeRange([myTextView.text length],0)]; – ThinkBonobo 2014-04-06 21:35:51

5

我想標準輸出重定向到一個NSTextView。

你自己的stdout?

這是否也適用於子過程的輸出?

肯定。

什麼可能是實現這一目標的最佳方法?

文件描述符是你的朋友在這裏。

創建一個管道(使用NSPipe或pipe(2))和dup2其寫入結束到STDOUT_FILENO。調用子進程時,不要設置它們的stdout;他們會繼承你的stdout,這是你的管道。 (但是,您可能想要關閉子進程中的讀取結束,但我不確定這是否有必要;請嘗試並找出結果,如果結果如此,則需要使用forkexec,並關閉它們之間的讀取端。)

使用kevent或NSFileHandle異步讀取管道讀取結尾。當新數據進入時,使用某種編碼解釋它並將其附加到文本視圖的內容。

如果文本視圖處於滾動視圖中,則應在追加到該滾動視圖之前檢查滾動位置。如果它最後,你可能會想要追加後跳回到最後。

+0

我編輯了一個非工作實現的問題?任何線索? – Sney 2010-03-09 08:48:35

+0

Snej:你有'dup2'的錯誤方法。然後你傳遞一個NSFileHandle指針作爲文件描述符來創建一個NSFileHandle。然後你假裝寫入結束是一個套接字並嘗試接受一個連接,儘管既沒有從listen(2)返回FD(因爲它們是管道而不是套接字)。修復'dup2'調用,不要假裝文件句柄指針是文件描述符,也不要試圖爲任一端創建另一個文件句柄,並嘗試從*讀取結束* *讀取*。 – 2010-03-09 18:32:19

0

對於iOS使用stderr而不是stdout。

NSPipe *pipe = [NSPipe pipe]; 
pipeHandle = [pipe fileHandleForReading]; 
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stderr)); 

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleNotification:) name: NSFileHandleReadCompletionNotification object: pipeHandle] ; 
[pipeHandle readInBackgroundAndNotify] ; 

-(void)handleNotification:(NSNotification *)notification{ 

    [pipeHandle readInBackgroundAndNotify] ; 
    NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ; 

} 
相關問題