Usando o NSTask: congelamento de aplicativos após retornar a saída
-
12-09-2019 - |
Pergunta
Oi eu tenho o seguinte código:
- (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];
}
O objetivo do Código é meio complicado, ele usa o OTool para obter uma lista das bibliotecas compartilhadas usadas por um binário, e ele usa o Sed e o AWK para filtrá -lo em um formato legível pela máquina. Apenas para testar, usei o binário do Mac OS X Textedit.App.
A questão é que o código é executado e retorna uma saída, mas congela o aplicativo. Eu passei por isso linha por linha e achei essa linha o problema:
dados = [[output fileHandleForReading] readDatatoEndoffile];
Essa linha em si está registrando a saída no console e, em seguida, congelando o aplicativo. Eu verifiquei isso excluindo todas as outras linhas após essa linha e ainda registra a saída e congela. Não há nada no depurador e nenhuma sugestão sobre como resolver esse problema seria muito apreciada.
Solução 2
A solução para esse problema era simples,
É um bug conhecido que, após o NSTask ser executado, todo o registro não funciona. Ele está retornando uma saída, simplesmente não está registrando -o. A solução foi adicionar esta linha:
[task setStandardInput:[NSPipe pipe]];
E tudo funciona bem :)
Outras dicas
Parece que você está perdendo um
[proc setStandardOutput:output];
Você tem uma barra extra no final da última declaração sed. Depois de removê -lo, o script funciona bem.
A saída deve ser criada com [NSPIPE PIPE] (não de propriedade) e, em seguida, a saída deve ser definida como a saída padrão com [Proc SetStandardOutput: Output
Mas a razão pela qual você está travando é porque você está liberando dados que não alocou, novo ou copiaram. Veja o Regras de gerenciamento de memória.
Veja também Quickies para nstask Para uma boa implementação limpa deste código.