Каков наилучший способ перенаправить стандартный вывод в 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. Когда поступают новые данные, интерпретируйте их, используя некоторую кодировку, и добавьте их к содержимому текстового представления.
Если текстовое представление находится в представлении прокрутки, вы должны проверить положение прокрутки перед добавлением к нему. Если это было в конце, вы, вероятно, захотите вернуться к концу после добавления.
Для 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] ;
}