Banging my head against a brick wall with this one.
Sending a command to the system and it takes a while to come back. I want to update an NSText field with a status before each system command.
When I do this, it doesn't update until after these tasks have completed, when it appears to catch up and do them all at once. So "send them to a DispatchQueue" I thought. I hadn't used them before, but I have read pages and pages and looked at example.
I am sending the system command with qos: utility and from what I've read the UI commands should stay in the main thread and get priority.
Even if I send the textbox.StringValue explicitly to DispatchQueue.main.async the same thing occurs
I know I am missing something, but the whole point of GCD seems to be to get around this issue, so I am very confused. I have tried a number of tests to work around this, with various qos levels and with sync and async queus, nothing seems to work.
Any help GREATLY appreciated!
Full simplified example ViewController.swift
queue (currently) declared on line 2 and called on line 24 (Swift 3 in XCode 8.2.1)
import Cocoa
let queue = DispatchQueue(label: "com.app.testqueue",qos: .utility)
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override var representedObject: Any? {
didSet
}
}
func runCommand(cmd : String, args : String...) -> (output: [String], error: [String], exitCode: Int32) {
var output : [String] = []
var error : [String] = []
let task = Process()
task.launchPath = cmd
task.arguments = args
let outpipe = Pipe()
task.standardOutput = outpipe
let errpipe = Pipe()
task.standardError = errpipe
queue.async {
task.launch()
}
let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
if var string = String(data: outdata, encoding: .utf8) {
string = string.trimmingCharacters(in: .newlines)
output = string.components(separatedBy: "\n")
}
let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
if var string = String(data: errdata, encoding: .utf8) {
string = string.trimmingCharacters(in: .newlines)
error = string.components(separatedBy: "\n")
}
task.waitUntilExit()
let status = task.terminationStatus
return (output, error, status)
}
@IBOutlet weak var textbox: NSTextField!
func msg(txt : String) -> () {
self.textbox.stringValue = txt
}
@IBAction func buttonPress(_ sender: NSButton) {
msg(txt: "Task 1")
let (output, error, status) = runCommand(cmd: "/usr/bin/say", args: "the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog")
print("program exited with status \(status)")
print (output)
msg(txt: "Task 2")
let (output2, error2, status2) = runCommand(cmd: "/usr/bin/say", args: "the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog")
print("program exited with status \(status2)")
print (output2)
}
}