Использование NSTask:приложение зависает после возврата вывода
-
12-09-2019 - |
Вопрос
Привет, у меня есть следующий код:
- (IBAction)runTask:(id)sender {
NSTask *proc;
NSPipe *output;
NSData *data;
NSString *buffer;
proc = [[NSTask alloc] init];
output = [[NSPipe alloc] init];
[proc setLaunchPath:@"/bin/sh"];
[proc setArguments:[NSArray arrayWithObjects: @"-c", @"/usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit | /usr/bin/awk 'NR>1{print $1}' | /usr/bin/sed -e '/@executable_path/d' -e 's/(.*)$//' -e 's/\\/Versions.*$//'", nil]];
[proc launch];
data = [[output fileHandleForReading] readDataToEndOfFile];
buffer = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"got: %@", buffer);
// Release
[proc release];
[output release];
[buffer release];
[data release];
}
Назначение кода довольно сложное: он использует otool для получения списка общих библиотек, используемых двоичным файлом, а затем использует sed и awk для фильтрации его в машиночитаемый формат.Просто для проверки я использовал двоичный файл TextEdit.app для Mac OS X.
Проблема в том, что код запускается и возвращает выходные данные, но затем зависает приложение.Я просмотрел его построчно и обнаружил, что проблема заключается в следующей строке:
данные = [[выходной fileHandleForReading] readDataToEndOfFile];
Эта строка сама регистрирует вывод на консоль, а затем замораживает приложение.Я проверил это, удалив все остальные строки после этой строки, но вывод все равно регистрируется и зависает.В отладчике ничего нет, и любые предложения по решению этой проблемы будут очень признательны.
Решение 2
Решение этой проблемы было простым:
Это известная ошибка, заключающаяся в том, что после выполнения NSTAsk вся регистрация не работает.Он возвращает результат, просто не записывает его.Решением было добавить эту строку:
[task setStandardInput:[NSPipe pipe]];
И все работает нормально :)
Другие советы
Похоже, вам не хватает
[proc setStandardOutput:output];
У вас есть дополнительная косая черта в конце последнего оператора sed.После его удаления скрипт работает нормально.
вывод должен быть создан с помощью [NSPipe Pipe] (не принадлежащий), а затем вывод должен быть установлен как стандартный вывод с помощью [proc setStandardOutput:выход]
Но причина сбоя заключается в том, что вы освобождаете данные, которые вы не выделяли, не создавали и не копировали.См. правила управления памятью.
Также см Быстрые файлы для NSTask для хорошей чистой реализации этого кода.