gngrwzrd

NSTask Runner with NSPipes for StdIn/StdOut/StdErr

May 5th, 2014
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //SCTaskRunner.h
  2. #import <Foundation/Foundation.h>
  3. @class SCTaskRunner;
  4. @protocol SCTaskRunnerDelegate <NSObject>
  5. @optional
  6. - (void) taskRunner:(SCTaskRunner *) taskRunner didReadDataFromStdOut:(NSData *) data;
  7. - (void) taskRunner:(SCTaskRunner *) taskRunner didReadDataFromStdErr:(NSData *) data;
  8. - (void) taskRunnerTerminated:(SCTaskRunner *) taskRunner;
  9. @end
  10. @interface SCTaskRunner : NSObject
  11. @property (assign) NSObject <SCTaskRunnerDelegate> * delegate;
  12. @property NSTask * task;
  13. @property NSPipe * standardInput;
  14. @property NSPipe * standardOutput;
  15. @property NSPipe * standardError;
  16. - (id) initWithStandardInput:(NSPipe *) pipe;
  17. @end
  18.  
  19. //SCTaskRunner.m
  20.  
  21. #import "SCTaskRunner.h"
  22.  
  23. @implementation SCTaskRunner
  24.  
  25. - (id) init {
  26.     self = [super init];
  27.     self.task = [[NSTask alloc] init];
  28.     [self setupPipesAndNotifications];
  29.     return self;
  30. }
  31.  
  32. - (id) initWithStandardInput:(NSPipe *) standardInput {
  33.     self = [self init];
  34.     self.standardInput = standardInput;
  35.     return self;
  36. }
  37.  
  38. - (void) setupPipesAndNotifications {
  39.     self.standardOutput = [[NSPipe alloc] init];
  40.     self.standardError = [[NSPipe alloc] init];
  41.    
  42.     //add notification to task for termination
  43.     NSNotificationCenter * nfc = [NSNotificationCenter defaultCenter];
  44.     [nfc addObserver:self selector:@selector(taskTerminated:) name:NSTaskDidTerminateNotification object:self.task];
  45.    
  46.     //add notifications for read data on standard out and standard error
  47.     self.task.standardOutput = self.standardOutput;
  48.     self.task.standardError = self.standardError;
  49.     [nfc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleReadCompletionNotification object:self.standardOutput.fileHandleForReading];
  50.     [nfc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleReadCompletionNotification object:self.standardError.fileHandleForReading];
  51.     [self.standardOutput.fileHandleForReading readInBackgroundAndNotify];
  52.     [self.standardError.fileHandleForReading readInBackgroundAndNotify];
  53.    
  54.     if(self.standardInput) {
  55.         self.task.standardInput = self.standardInput;
  56.     }
  57. }
  58.  
  59. - (void) dataAvailable:(NSNotification *) notification {
  60.     NSData * data = [notification.userInfo objectForKey:NSFileHandleNotificationDataItem];
  61.     if(notification.object == self.standardOutput.fileHandleForReading) {
  62.         if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadDataFromStdOut:)]) {
  63.             [self.delegate taskRunner:self didReadDataFromStdOut:data];
  64.         }
  65.     } else if(notification.object == self.standardError.fileHandleForReading) {
  66.         if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadDataFromStdErr:)]) {
  67.             [self.delegate taskRunner:self didReadDataFromStdErr:data];
  68.         }
  69.     }
  70. }
  71.  
  72. - (void) taskTerminated:(NSNotification *) notification {
  73.     if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunnerTerminated:)]) {
  74.         [self.delegate taskRunnerTerminated:self];
  75.     }
  76. }
  77.  
  78. - (void) dealloc {
  79.     NSLog(@"DEALLOC: SCTaskRunner");
  80.     [[NSNotificationCenter defaultCenter] removeObserver:self];
  81.     self.task = nil;
  82.     self.delegate = nil;
  83.     self.standardOutput = nil;
  84.     self.standardError = nil;
  85.     self.standardInput = nil;
  86. }
  87.  
  88. @end
Advertisement
Add Comment
Please, Sign In to add comment