2016-06-29 7 views
0

zurückgeben Ich habe zwei Klassen in Swift, einer ist ein ViewController.Swift, ein anderer hat eine Business-Logik namens Brain.Swift. In Brain.swift habe ich eine Klasse, die eine Funktion namens convert() enthält, die eine NSTask ausführt.Wie NSLog-Ausgabe in Echtzeit als eine Klasseneigenschaft in Swift

In ViewController.swift erfolgt die Aktualisierung der Benutzeroberfläche.

Was ich erreichen möchte, ist die Ausgabe der NSTask von convert() in eine TextView im ViewController.

Ich habe die Lösung von this answer implementiert, aber ich bin ein bisschen ein Anfänger, also bin ich mir nicht sicher, wie man es als eine Klasseneigenschaft in Echtzeit zurückgibt, um für andere Klassen zugänglich zu sein.

Brain.swift

import Foundation 


internal func convert(chosenFile: NSURL, addText: (newText: String) -> Void) { 


    let bundle = NSBundle.mainBundle() 

    let task = NSTask() 

    let outputPipe = NSPipe() 

    task.standardOutput = outputPipe 
    let outHandle = outputPipe.fileHandleForReading 

    outHandle.readabilityHandler = { outputPipe in 
     if let line = String(data: outputPipe.availableData, encoding: NSUTF8StringEncoding) { 
      addText(newText: line) 
     } else { 
      print("Error decoding data: \(outputPipe.availableData)") 
     } 
    } 

    task.launch() 
    task.waitUntilExit() 

} 

ViewController.swift

@IBAction func Run(sender: AnyObject) { 

    let qualityOfServiceClass = QOS_CLASS_USER_INITIATED 
    let userInitiatedQueue = dispatch_get_global_queue(qualityOfServiceClass, 0) 
    dispatch_async(userInitiatedQueue, { 
     self.btnConvert.enabled = false 
     self.btnSelect.enabled = false 
     self.activitySpinner.hidden = false 
     self.activitySpinner.startAnimation(self) 


     convert(self.inputFile.chosenFile) { newText in 
       self.statusText.stringValue = "\(newText)" 
     } 
    }) 

    dispatch_async(dispatch_get_main_queue(), {() -> Void in 
     self.statusText.stringValue = "Done!" 
     self.activitySpinner.hidden = true 
     self.activitySpinner.stopAnimation(self) 

     self.btnSelect.enabled = true 

    }) 
} 

Antwort

0

Dies sollte funktionieren:

func convert(chosenFile: NSURL, addText: (newText: String) -> Void) { 
    let task = NSTask() 

    // Set up task 

    let pipe = NSPipe() 
    task.standardOutput = pipe 
    let outHandle = pipe.fileHandleForReading 

    outHandle.readabilityHandler = { pipe in 
     if let line = String(data: pipe.availableData, encoding: NSUTF8StringEncoding) { 
      addText(newText: line) 
     } else { 
      print("Error decoding data: \(pipe.availableData)") 
     } 
    } 

    task.launch() 
} 

Sie es so nennen kann:

Ich habe eine Funktion aus Ihrer Klasse gemacht, weil es keinen Grund für eine Klasse gibt, wenn Sie es nur für eine einzige Funktion verwenden. Der readabilityHandler Ansatz vereinfacht auch Ihren Code erheblich.

Ich habe auch diese Art von Updates zu der genannten Frage hinzugefügt.

+0

Vielen Dank, aber ich kann den Text mit dieser Lösung nicht abrufen. Ich habe die Klasse in eine Funktion umgewandelt, aber anscheinend wird nichts innerhalb des Funktionsaufrufs convert() {} ausgeführt. Ich habe dies mit einem Debugger überprüft. Muss es mit GCD multithreaded sein? Ist readabilityHandler bereits multithreaded? – user43633

+0

@ user43633 Wenn es nicht ausgeführt wird, rufen Sie es nicht an, überprüfen Sie es erneut oder zeigen Sie den entsprechenden Code an. Ja, 'readabilityHandler' ruft bereits einen eigenen Thread auf. Beachten Sie, dass diese Funktion nicht bis zum Abschluss der Aufgabe wartet, sondern die angegebene Schließung verwendet, um Ihnen Feedback zu geben, wenn etwas passiert ist. – Kametrixom

+0

Danke für die Bestätigung, dass über readabiltyHandler, ich habe mit dem entsprechenden Code aktualisiert. Ich denke, ich könnte eine falsche Implementierung von Threads haben, die zu meinem Problem beiträgt, hat wahrscheinlich nichts mit Ihrer Lösung zu tun. – user43633

Verwandte Themen