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

前端 未结 4 1284
南笙
南笙 2020-12-03 12:49

Hi: I want to redirect stdout to a NSTextView. Could this also work with outputs of subprocesses? What might be the best way to achieve this?

EDIT:

相关标签:
4条回答
  • 2020-12-03 13:36

    For iOS use stderr instead of 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] ;
    
    }
    
    0 讨论(0)
  • 2020-12-03 13:39

    Have a look at PseudoTTY.app!

    0 讨论(0)
  • 2020-12-03 13:41

    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. I'm including my solution here. "pipe" and "pipeReadHandle" are declared in the interface. In the init method I included the following code:

    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

    [pipeReadHandle readInBackgroundAndNotify] ;
    NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ;
    // Do whatever you want with str 
    
    0 讨论(0)
  • 2020-12-03 13:42

    I want to redirect stdout to a 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. When invoking subprocesses, don't set their stdout; they'll inherit your stdout, which is your pipe. (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.)

    Read from the read end of the pipe in the background asynchronously, using either kevent or 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.

    0 讨论(0)
提交回复
热议问题