|
#1
| ||||
| ||||
|
An earlier thread had information on using NSTimer-s to read from an NSPipe attached to an NSTask. This required regular polling and reading from the NSPipe which seems like kind of a silly way to do it. Apparently there's a better way, and boy am I glad it's there. I'll share it with you. Let's assume you have some controller class that's going to start up the NSTask and do something with the NSPipe you read. Maybe you're just going to display the results in an NSTextView that you created in Project Builder. In the controller's .h file, let's declare some variables: Code: NSTask *_task; NSFileHandle *_fileHandle; As always we launch the NSTask: Code: NSPipe *pipe = [NSPipe pipe]; _fileHandle = [pipe fileHandleForReading]; [_fileHandle readInBackgroundAndNotify]; _task = [[NSTask alloc] init]; [_task setLaunchPath:@"/bin/ls"]; [_task setStandardOutput: pipe]; [_task setStandardError: pipe]; // arguments if you want 'em [_task launch]; Make up an init method like this: Code: -(id)init
{
[super init];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector( readPipe: )
name:NSFileHandleReadCompletionNotification
object:nil];
return self;
}
Code: -(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Code: -(void)readPipe: (NSNotification *)notification
{
NSData *data;
NSString *text;
if( [notification object] != _fileHandle )
return;
data = [[notification userInfo]
objectForKey:NSFileHandleNotificationDataItem];
text = [[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding];
// Do something with your text
// ...
[text release];
if( _task )
[_fileHandle readInBackgroundAndNotify];
}
Now isn't active notification much better than polling? Let me know, y'all, if I have any errors. -Rob
__________________ There are only 10 kinds of people in the world: Those who understand binary, and those who don't. Last edited by rharder; July 9th, 2001 at 08:19 AM. |
|
#2
| ||||
| ||||
|
Thank you! I have been looking for <i>exactly</i> this! I've been having to wait until the task has finished before seeing the results. This is much much better! Now onto my next mountain: opening a png file that's being written to and displaying it on the fly. Sounds like fun |
|
#3
| ||||
| ||||
|
That would be a trick. I wonder if you could 'tail' a binary file. Oh, and one of the reasons that polling or waiting until the end of an NSTask is a bad idea is that apparently there's only an 8K or so buffer in the pipe somewhere, and you could lose data otherwise. I think this technique should get around that. Maybe. Good luck. -Rob
__________________ There are only 10 kinds of people in the world: Those who understand binary, and those who don't. |
|
#4
| |||
| |||
| Quote:
|
|
#5
| ||||
| ||||
|
Oh, good. So even though it may be less efficient, you could still just use NSTimers (if you really really wanted to) to read data instead of the "active" method mentioned above. -Rob
__________________ There are only 10 kinds of people in the world: Those who understand binary, and those who don't. |
|
#6
| ||||
| ||||
|
Rob, I found a limitation in this...sorta kinda. I was wondering if you could help me out. This works great for input/output (whichever you want to call it) that's not too long, but if the data from the pipe takes longer to display than it takes for the task to finish executing, the data stops displaying. I'm guessing this is from the if(task).... line. I know this is the reason the text gets cut in the display (I'm using an NSTextView to display the results) because sometimes the task won't end (or my app isn't getting that it ended), and all the data gets displayed. (BTW, if anyone out there is having a problem with tasks not finishing, I found a strange workaround. Not in the code, but in the running app. If you click on one of the menus, which won't open, then click on the desktop, then click back on your window, the app will get that the task has finished...for whatever reason. This is most likely a bug in my code, but I'd thought I'd share in case someone else was seeing this). Anyway, I was wondering if you could help me think of a way to get the last bit of data from the pipe displayed. I tried adding a [_fileHandle readInBackgroundAndNotify] to the task finished part (BTW, I have two observers added in init - seems to work fine, but I'm new to Cocoa, and so I'm asking if that's alright? One for catching the data from the pipe, and one for catching when the task quits). That didn't work. I tried making an else after the if (task) line, but that didn't really work either...I had set up an NSTimer to fire a few times and then had it do [_fileHandle readInBackgroundAndNotify], but it didn't get anything else. Any thoughts to what may be happening? |
|
#7
| ||||
| ||||
|
So, when there's a lot of output, some of the last bit of data doesn't get read? And you tried reading after the Task Finished notification too? Weird. I had something weird like that when I 'tail'ed the system log, but since that task never finished, I never quite had the problem you describe. I did discover that I had to manually scroll the NSTextView a few times to "reset" the viewing. I wonder if some of this comes from threading issues between the task and the main event-dispatching thread. I haven't worried about it too much, figuring it might just be little bugs that will get worked out or explained in a release note some time. -Rob
__________________ There are only 10 kinds of people in the world: Those who understand binary, and those who don't. |
|
#8
| |||
| |||
| Get all the output
To get all of the output change the If statement to look at the data structure instead of the program. ie. If( data != 0 ) [_fileHandle readInBackgroundAndNotify]; This will allow the remainder of the pipe to be read after the unix program finishes executing. |
![]() |
| Bookmarks |
| Thread Tools | |
|
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Looking for Software: Bookmarks to be read by both Windows and Mac? | Sogni | Mac OS X System & Mac Software | 0 | August 29th, 2003 05:28 PM |
| DVR-104 won't read or write DVD-R's | Bad Co | Hardware & Peripherals | 1 | March 14th, 2003 06:29 PM |
| Won’t read DVD-video discs, and slow CD read speed | koim | Hardware & Peripherals | 1 | March 11th, 2003 02:38 PM |
| Is there a way to know if your recipient read the email you sent them? | chemistry_geek | Mac OS X System & Mac Software | 7 | October 3rd, 2002 01:49 PM |