Here is an example of async NSTask that runs a unix script. The Unix script has echo commands that return the current state to a standard error as follows:
echo "working" >&2
This is processed by the notification center and sent to the display.
To update a specific progress bar, simply send status updates β25.0β to β26.0β and convert them to float and send to the progress bar.
note: I got this work after a lot of experimentation and with many tips from this site and other links. therefore, I hope this will be useful to you.
Here are the announcements:
NSTask *unixTask; NSPipe *unixStandardOutputPipe; NSPipe *unixStandardErrorPipe; NSPipe *unixStandardInputPipe; NSFileHandle *fhOutput; NSFileHandle *fhError; NSData *standardOutputData; NSData *standardErrorData;
Here are the main software modules:
- (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
CocoaEv
source share