View difference between Paste ID: b0hJK5EZ and ycckN5ny
SHOW: | | - or go back to the newest paste.
1-
//SCTaskRunner.h
1+
//// header
2
#import <Foundation/Foundation.h>
3
@class SCTaskRunner;
4
@protocol SCTaskRunnerDelegate <NSObject>
5
@optional
6
- (void) taskRunner:(SCTaskRunner *) taskRunner didReadData:(NSData *) data;
7
- (void) taskRunner:(SCTaskRunner *) taskRunner didReadDataFromStdOut:(NSData *) data;
8
- (void) taskRunner:(SCTaskRunner *) taskRunner didReadDataFromStdErr:(NSData *) data;
9
- (void) taskRunnerTerminated:(SCTaskRunner *) taskRunner;
10-
@interface SCTaskRunner : NSObject
10+
11
12
@interface SCTaskRunner : NSObject {
13
	BOOL _terminated;
14
}
15
@property (assign) NSObject <SCTaskRunnerDelegate> * delegate;
16
@property BOOL collectDataUntilTerminated;
17
@property NSTask * task;
18
@property NSPipe * standardInput;
19-
//SCTaskRunner.m
19+
20
@property NSPipe * standardError;
21
@property NSMutableData * data;
22
- (id) initWithStandardInput:(NSPipe *) pipe;
23
@end
24
25
////implementation
26
27
#import "SCTaskRunner.h"
28
29
@implementation SCTaskRunner
30
31
- (id) init {
32
	self = [super init];
33
	self.task = [[NSTask alloc] init];
34
	self.data = [NSMutableData data];
35
	[self setupPipesAndNotifications];
36
	return self;
37
}
38
39
- (id) initWithStandardInput:(NSPipe *) standardInput {
40
	self = [self init];
41
	self.standardInput = standardInput;
42
	return self;
43
}
44
45
- (void) setupPipesAndNotifications {
46
	self.standardOutput = [[NSPipe alloc] init];
47
	self.standardError = [[NSPipe alloc] init];
48
	self.task.standardOutput = self.standardOutput;
49-
	[nfc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleReadCompletionNotification object:self.standardOutput.fileHandleForReading];
49+
50-
	[nfc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleReadCompletionNotification object:self.standardError.fileHandleForReading];
50+
51-
	[self.standardOutput.fileHandleForReading readInBackgroundAndNotify];
51+
52-
	[self.standardError.fileHandleForReading readInBackgroundAndNotify];
52+
53
	//add notification to task for termination
54
	[nfc addObserver:self selector:@selector(taskTerminated:) name:NSTaskDidTerminateNotification object:self.task];
55
	
56
	//add notifications for read data on standard out and standard error
57
	[nfc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleDataAvailableNotification object:self.standardOutput.fileHandleForReading];
58
	[nfc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleDataAvailableNotification object:self.standardError.fileHandleForReading];
59
	[self.standardOutput.fileHandleForReading waitForDataInBackgroundAndNotify];
60-
	NSData * data = [notification.userInfo objectForKey:NSFileHandleNotificationDataItem];
60+
	[self.standardError.fileHandleForReading waitForDataInBackgroundAndNotify];
61-
	if(notification.object == self.standardOutput.fileHandleForReading) {
61+
62-
		if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadDataFromStdOut:)]) {
62+
63-
			[self.delegate taskRunner:self didReadDataFromStdOut:data];
63+
64
	}
65-
	} else if(notification.object == self.standardError.fileHandleForReading) {
65+
66-
		if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadDataFromStdErr:)]) {
66+
67-
			[self.delegate taskRunner:self didReadDataFromStdErr:data];
67+
- (void) dataAvailableForFileHandle:(NSFileHandle *) fileHandle {
68
	NSData * data = [fileHandle availableData];
69
	
70
	if(data.length > 0) {
71
		if(self.collectDataUntilTerminated) {
72
			[self.data appendData:data];
73
		} else {
74
			
75
			if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadData:)]) {
76
				[self.delegate taskRunner:self didReadData:data];
77
			}
78
			
79
			if(fileHandle == self.standardOutput.fileHandleForReading) {
80
				if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadDataFromStdOut:)]) {
81
					[self.delegate taskRunner:self didReadDataFromStdOut:data];
82
				}
83
			}
84
			
85
			if(fileHandle == self.standardError.fileHandleForReading) {
86
				if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunner:didReadDataFromStdErr:)]) {
87
					[self.delegate taskRunner:self didReadDataFromStdErr:data];
88
				}
89
			}
90
		}
91
	}
92
	
93
	if(!_terminated) {
94
		[fileHandle waitForDataInBackgroundAndNotify];
95
	}
96
}
97
98
- (void) dataAvailable:(NSNotification *) notification {
99
	NSFileHandle * fileHandle = notification.object;
100
	[self dataAvailableForFileHandle:fileHandle];
101
}
102
103
- (void) taskTerminated:(NSNotification *) notification {
104
	_terminated = TRUE;
105
	[self dataAvailableForFileHandle:self.standardOutput.fileHandleForReading];
106
	[self dataAvailableForFileHandle:self.standardError.fileHandleForReading];
107
	if(self.delegate && [self.delegate respondsToSelector:@selector(taskRunnerTerminated:)]) {
108
		[self.delegate taskRunnerTerminated:self];
109
	}
110
}
111
112
- (void) dealloc {
113
	NSLog(@"DEALLOC: SCTaskRunner");
114
	[[NSNotificationCenter defaultCenter] removeObserver:self];
115
	[self.task terminate];
116
	self.task = nil;
117
	self.delegate = nil;
118
	self.standardOutput = nil;
119
	self.standardError = nil;
120
	self.standardInput = nil;
121
}
122
123
@end