I am making a macOS app. I have a task (a script) that I am running with Process() in Swift 3. When I press a button (button.State == NSOnState), I would like the task to repeating n times, and terminate earlier until the button is pressed again (button.State == NSOffState).
I looked up how to repeat a task, and it looks possible with a simple for loop – for i in {1..n}.
Now, the problem I am having is that it doesn't seem to be possible to call a task multiple times. When I try to call the task the second time, I get an error in the console:
[General] task already launched
Here is my code:
@IBAction func buttonPressed(_ sender: Any) {
let script = "for i in {1..5}; do echo \"hi\"; done; sleep 1"
let task = Process()
task.terminationHandler = self.commandTerminationHandler
task.launchPath = "/bin/bash"
task.arguments = ["-c", script]
if button.state == NSOnState {
task.launch() // launches task
task.waitUntilExit() // waits until task has been completed (about 1 second)
task.terminate() // (should) terminate the task. (The console error occurs with or without this line)
task.launch() // tries launching the task again, but this results in the console error.
print("The task was launched twice")
} else {
// task.terminate()
}
}
I googled this error, and found [this][https://forums.macrumors.com/threads/nstask-not-terminating.1617855/#post-17677541]:
The error isn't that the task is still running. It's that the task has already run and completed, and can't be started again. You'll need to create a new NSTask object to run the task again.
So I need to make a new NSTask (or Process as of Swift 3) and keep making new ones to repeat the code forever. This sound very complicated (as if I'm using a workaround) and is probably inefficient.
Is there a better way to repeat a Process in Swift 3?
For the sake of completeness, I'd also like to mention that I considered using for i in {1..n} do ... done directly in script. This has one problem:
- It doesn't look like it's possible to stop the task when the button is pressed again. This is because if I run
task.terminate(), I get the error "task not launched." The only way I can stop it is by runningkillall bashin my Terminal, which doesn't seem like a nice solution. To do this in Xcode, I'd need make a Process to kill bash with bash... which is strange.