简体   繁体   English

将标准输出重定向到Cocoa中的NSTextView的最佳方法是什么?

[英]What is the best way to redirect stdout to NSTextView in Cocoa?

Hi: I want to redirect stdout to a NSTextView. 嗨:我想将标准输出重定向到NSTextView。 Could this also work with outputs of subprocesses? 这也可以与子流程的输出一起使用吗? What might be the best way to achieve this? 实现此目标的最佳方法是什么?

EDIT: According to Peter Hosey answer I implemented the following. 编辑:根据彼得·霍西的答案,我实现了以下内容。 But I do not get a notification. 但是我没有收到通知。 What am I doing wrong? 我究竟做错了什么?

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];

I was looking to do the same thing and came across this post. 我一直在想做同样的事情,并且偶然发现了这篇文章。 I was able to figure it out after reading this and Apple's documentation. 阅读本文和Apple文档后,我能够弄清楚。 I'm including my solution here. 我在这里包括我的解决方案。 "pipe" and "pipeReadHandle" are declared in the interface. 在接口中声明“ pipe”和“ pipeReadHandle”。 In the init method I included the following code: 在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] ;

The handleNotification: method is handleNotification:方法是

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

I want to redirect stdout to a NSTextView. 我想将标准输出重定向到NSTextView。

Your own stdout? 你自己的标准输出?

Could this also work with outputs of subprocesses? 这也可以与子流程的输出一起使用吗?

Sure. 当然。

What might be the best way to achieve this? 实现此目标的最佳方法是什么?

File descriptors are your friend here. 文件描述符在这里是您的朋友。

Create a pipe (using either NSPipe or pipe(2) ) and dup2 its write end onto STDOUT_FILENO . 创建一个管道(使用NSPipe或pipe(2) )并将其写端dup2写入STDOUT_FILENO When invoking subprocesses, don't set their stdout; 调用子流程时,请勿设置其标准输出; they'll inherit your stdout, which is your pipe. 他们将继承您的stdout,即您的管道。 (You may want to close the read end in the subprocess, though. I'm not sure whether this will be necessary; try it and find out. If it does turn out to be, you'll need to use fork and exec , and close the read end in between.) (不过,您可能想在子流程中关闭读取端。我不确定是否有必要;尝试并找出来。如果确实如此,则需要使用forkexec ,并关闭两者之间的读取端。)

Read from the read end of the pipe in the background asynchronously, using either kevent or NSFileHandle. 使用kevent或NSFileHandle在后台异步读取管道的读取端。 When new data comes in, interpret it using some encoding and append it to the contents of the text view. 当输入新数据时,请使用某种编码对其进行解释,并将其附加到文本视图的内容中。

If the text view is in a scroll view, you should check the scroll position before appending to it. 如果文本视图处于滚动视图中,则应在附加到滚动视图之前检查滚动位置。 If it was at the end, you'll probably want to jump it back to the end after appending. 如果在末尾,则可能需要在追加后将其跳回到末尾。

看看PseudoTTY.app

For iOS use stderr instead of stdout. 对于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] ;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM