Running a script with NSTask and NSPipe

:  ~ 45 sec read

Say you have a Mac app and you want to run a script, either to perform some action, or to return something, here's one way to do it.

First, we create an NSTask, set the launch path of the handler, in our case ruby (we will use the default one, to be sure it exists), and the required parameters, if required:

let task = Process()
task.launchPath = "/usr/bin/ruby"
task.arguments = [
  Bundle.main.path(forResource: myScript, ofType: "rb")!,
  parameter1
]

This would be the same as running in the terminal:

ruby /path/to/myScript parameter1

All good, but what if the script returns something and we want to use that? NSPipe to the rescue:

let pipe = Pipe()
task.standardOutput = pipe
task.launch()

let resultData = pipe.fileHandleForReading.readDataToEndOfFile()
let resultString = String(data: resultData, encoding: .utf8)

Returning a value with a script is as easy as printing:

def optional_method
  'I am the return value'
end

puts optional_method + ' of a script'

This would result in resultString's value to be I am the return value of a script.