Вот пример асинхронного NSTask, выполняющего сценарий Unix.В сценарии Unix есть echo
команды, которые возвращают текущий статус к стандартной ошибке, например:
echo "working" >&2
Это обрабатывается центром уведомлений и отправляется на дисплей.
Чтобы обновить определенный индикатор выполнения, просто отправьте обновления состояния, такие как «25,0», «26,0», и преобразуйте их в число с плавающей точкой и отправьте в индикатор выполнения.
примечание: я получил эту работу после многих экспериментов и с использованием многих советов с этого сайта и других ссылок.поэтому я надеюсь, что это полезно для вас.
Вот объявления:
NSTask *unixTask;
NSPipe *unixStandardOutputPipe;
NSPipe *unixStandardErrorPipe;
NSPipe *unixStandardInputPipe;
NSFileHandle *fhOutput;
NSFileHandle *fhError;
NSData *standardOutputData;
NSData *standardErrorData;
Вот основные программные модули:
- (IBAction)buttonLaunchProgram:(id)sender {
[_unixTaskStdOutput setString:@"" ];
[_unixProgressUpdate setStringValue:@""];
[_unixProgressBar startAnimation:sender];
[self runCommand];
}
- (void)runCommand {
//setup system pipes and filehandles to process output data
unixStandardOutputPipe = [[NSPipe alloc] init];
unixStandardErrorPipe = [[NSPipe alloc] init];
fhOutput = [unixStandardOutputPipe fileHandleForReading];
fhError = [unixStandardErrorPipe fileHandleForReading];
//setup notification alerts
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(notifiedForStdOutput:) name:NSFileHandleReadCompletionNotification object:fhOutput];
[nc addObserver:self selector:@selector(notifiedForStdError:) name:NSFileHandleReadCompletionNotification object:fhError];
[nc addObserver:self selector:@selector(notifiedForComplete:) name:NSTaskDidTerminateNotification object:unixTask];
NSMutableArray *commandLine = [NSMutableArray new];
[commandLine addObject:@"-c"];
[commandLine addObject:@"/usr/bin/kpu -ca"]; //put your script here
unixTask = [[NSTask alloc] init];
[unixTask setLaunchPath:@"/bin/bash"];
[unixTask setArguments:commandLine];
[unixTask setStandardOutput:unixStandardOutputPipe];
[unixTask setStandardError:unixStandardErrorPipe];
[unixTask setStandardInput:[NSPipe pipe]];
[unixTask launch];
//note we are calling the file handle not the pipe
[fhOutput readInBackgroundAndNotify];
[fhError readInBackgroundAndNotify];
}
-(void) notifiedForStdOutput: (NSNotification *)notified
{
NSData * data = [[notified userInfo] valueForKey:NSFileHandleNotificationDataItem];
NSLog(@"standard data ready %ld bytes",data.length);
if ([data length]){
NSString * outputString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSTextStorage *ts = [_unixTaskStdOutput textStorage];
[ts replaceCharactersInRange:NSMakeRange([ts length], 0)
withString:outputString];
}
if (unixTask != nil) {
[fhOutput readInBackgroundAndNotify];
}
}
-(void) notifiedForStdError: (NSNotification *)notified
{
NSData * data = [[notified userInfo] valueForKey:NSFileHandleNotificationDataItem];
NSLog(@"standard error ready %ld bytes",data.length);
if ([data length]) {
NSString * outputString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[_unixProgressUpdate setStringValue:outputString];
}
if (unixTask != nil) {
[fhError readInBackgroundAndNotify];
}
}
-(void) notifiedForComplete:(NSNotification *)anotification {
NSLog(@"task completed or was stopped with exit code %d",[unixTask terminationStatus]);
unixTask = nil;
[_unixProgressBar stopAnimation:self];
[_unixProgressBar viewDidHide];
if ([unixTask terminationStatus] == 0) {
[_unixProgressUpdate setStringValue:@"Success"];
}
else {
[_unixProgressUpdate setStringValue:@"Terminated with non-zero exit code"];
}
}
@end