How do I set the text of a label from outside of viewDidAppear?

前提是你 提交于 2021-02-11 13:24:45

问题


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()
        }
    }
}

来源:https://stackoverflow.com/questions/62333844/how-do-i-set-the-text-of-a-label-from-outside-of-viewdidappear

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!