Каков наилучший способ перенаправить стандартный вывод в NSTextView в Какао?

Привет: я хочу перенаправить стандартный вывод в NSTextView. Может ли это также работать с выходами подпроцессов? Какой может быть лучший способ достичь этого?

РЕДАКТИРОВАТЬ: Согласно ответу Питера Хоси я реализовал следующее. Но я не получаю уведомления. Что я делаю неправильно?

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

4 ответа

Решение

Я хотел сделать то же самое и наткнулся на этот пост. Я смог понять это после прочтения этого и документации 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 

Я хочу перенаправить стандартный вывод в NSTextView.

Ваш собственный стандартный вывод?

Может ли это также работать с выходами подпроцессов?

Конечно.

Какой может быть лучший способ достичь этого?

Файловые дескрипторы - ваш друг здесь.

Создайте канал (используя NSPipe или pipe (2)) и дублируйте его конец записи на STDOUT_FILENO, При вызове подпроцессов не устанавливайте их стандартный вывод; они унаследуют ваш стандартный вывод, который является вашей трубкой. (Возможно, вы захотите закрыть конец чтения в подпроцессе. Я не уверен, будет ли это необходимо, попробуйте и выясните. Если это так, вам нужно будет использовать fork а также execи закройте конец чтения между ними.)

Чтение с конца чтения канала в фоновом режиме асинхронно, используя либо kevent или NSFileHandle. Когда поступают новые данные, интерпретируйте их, используя некоторую кодировку, и добавьте их к содержимому текстового представления.

Если текстовое представление находится в представлении прокрутки, вы должны проверить положение прокрутки перед добавлением к нему. Если это было в конце, вы, вероятно, захотите вернуться к концу после добавления.

Посмотрите на PseudoTTY.app!

Для 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] ;

}
Другие вопросы по тегам