问题
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