I'm writing a Mac (Swift) application on Xcode which gets data from a command and asynchronously changes the stringValue of some text in the window. I already figured out the asynchronous part from here, but I can't seem to figure out how to actually change the text, since Xcode seems to require it to be in viewDidAppear. Unfortunately I can't put the function which runs the command in viewDidAppear since it is called by another file and needs to be a public func (as far as I know).
Here are a couple of methods I tried:
1. Call a function inside viewDidAppear which changes the text:
self.viewDidAppear().printText("testing!") // this part is where the "New Output" line is on the attached link above
...
override func viewDidAppear() {
    func printText(_ string: String) {
        textLabel.stringValue = string
    }
}
Result: Value of tuple type '()' has no member 'printText' (on the first line)
2. Change an already-declared variable to the current message, then use Notification Center to tell viewDidAppear to change the text.
var textToPrint = "random text" // directly inside the class
let nc = NotificationCenter.default // directly inside the class
...
self.textToPrint = "testing!" // in place of the "New Output" line in the link above
self.nc.post(name: Notification.Name("printText"), object: nil) // in place of the "New Output" line in the link above
...
@objc func printText2() { // directly inside the class
    textLabel.stringValue = textToPrint // directly inside the class
} // directly inside the class
...
override func viewDidAppear() {
        nc.addObserver(self, selector: #selector(printText2), name: Notification.Name("printText"), object: nil)
}
For this one, I had to put printText2 outside of viewDidAppear because apparently selectors (for Notification Center) only work if you do that.
Result: NSControl.stringValue must be used from main thread only (on textLabel.stringValue line).
Also, the text never changes.
So I need to either somehow change the label's text directly from the asynchronous function, or to have viewDidAppear do it (also transmitting the new message).
...................................................................
Extra project code requested by Upholder of Truth
import Cocoa
class VC_image: NSViewController, NSWindowDelegate {
    @IBOutlet var textLabel: NSTextField!
    public func processImage(_ path: String) { // this function is called by another file
        previewImage()
    }
    public func previewImage() {
        if let path = Bundle.main.path(forResource: "bashscript", ofType: "sh") {
            let task3 = Process()
            task3.launchPath = "/bin/sh"
            task3.arguments = [path]
            let pipe3 = Pipe()
            task3.standardOutput = pipe3
            let outHandle = pipe3.fileHandleForReading
            outHandle.readabilityHandler = { pipe3 in
                if let line = String(data: pipe3.availableData, encoding: String.Encoding.utf8) {
                    // Update your view with the new text here
                    let messageToPrint = line.components(separatedBy: " ")
                    if (messageToPrint.count == 6) {
                        DispatchQueue.main.async {
                            self.textLabel.stringValue = "testing!"
                        }
                    }
                } else {
                    print("Error decoding data: \(pipe3.availableData)")
                }
            }
            task3.launch()
        }
    }
}