citelao
citelao

Reputation: 6076

Send value from NSTextField to constantly running NSTask

There have been a couple of NSTask related questions, but after paging through them I still have no idea what to do.

I'm writing a frontend for a java server in Cocoa, launched by java -Xmx1024M -Xms1024M -jar server.jar nogui (I've left out the nogui arg in my current code so as not to fill up my computer with unnecessary orphaned instances of server).

My current code correctly runs the .jar file; now I need a way to capture (and parse) output and send input to the process.

server = [[NSTask alloc] init];
pipe = [NSPipe pipe];
NSArray *args = [NSArray arrayWithObjects:@"-Xms1024M",
                    @"-Xmx1024M",
                    @"-jar",
                    @"server.jar",
                    nil];

[server setLaunchPath:@"/usr/bin/java"];
[server setCurrentDirectoryPath:@"MyApp.app/Contents/Resources/"];
[server setArguments:args];
[server setStandardOutput:pipe];
[server setStandardInput:pipe];
[server launch];

I've read up on NSPipe and NSTask and everything, but I can't seem an answer geared towards my problem:

EDIT: Or should I use launchd? How would I do that?

Upvotes: 1

Views: 567

Answers (1)

rob mayoff
rob mayoff

Reputation: 385930

You need to make two pipes: one for the task's standard input, and another for the task's standard output. What you're doing right now connects the task's output to its own input.

Something like this:

@interface ServerController : NSObject
@property (strong) NSFileHandle *standardInput;
@property (strong) NSFileHandle *standardOutput;
@end

@implementation ServerController

...

- (void)launchServer {
    NSPipe *standardInputPipe = [NSPipe pipe];
    self.standardInput = standardInputPipe.fileHandleForWriting;
    NSPipe *standardOutputPipe = [NSPipe pipe];
    self.standardOutput = standardOutputPipe.fileHandleForReading;
    ...
    server.standardInput = standardInputPipe;
    server.standardOutput = standardOutputPipe;
    [server launch];
}

...

Now you can write to the server by sending the writeData: message to the standardInput property of the ServerController instance. To read from the server, you'll want to use either readInBackgroundAndNotify or readabilityHandler on the standardOutput property.

Upvotes: 4

Related Questions