2016-06-29 6 views
0

私はSwiftに2つのクラスを持ち、1つはViewController.swiftで、もう1つはBrain.swiftというビジネスロジックを持っています。 Brain.swiftには、NSTaskを実行するconvert()という関数を含むクラスがあります。SwiftのクラスプロパティとしてリアルタイムでNSLog出力を返す方法

ViewController.swiftでは、すべてのUIの更新が行われます。

私が達成したいのは、convert()のNSTaskの出力をViewControllerのTextViewに取り込むことです。

私はthis answerから解決策を実装しましたが、私は初心者ですから、他のクラスからアクセスできるようにリアルタイムでクラスプロパティとして返す方法がわかりません。

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 

    }) 
} 

答えて

0

これは動作するはずです:

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

をあなたはこのようにそれを呼び出すことができます

convert(myURL) { newText in 
    print("New output available: \(newText)") 
} 

私はあなたのクラスから機能を作りました。なぜなら、あなたがただ一つの機能のためにそれを使うつもりなら、クラスの理由がないからです。 readabilityHandlerアプローチはまた、コードを大幅に簡素化します。

私は、上記の質問を更新するこの方法を追加しました。

+0

ありがとうございますが、このソリューションを使用してテキストを取得することができません。クラスを関数に変換しましたが、convert(){}関数呼び出しの中の何かが実行されていないようです。私はデバッガでこれをチェックしました。 GCDでマルチスレッド化する必要がありますか? readabilityHandlerはすでにマルチスレッド化されていますか? – user43633

+0

@ user43633実行されていない場合は、呼び出していないか、再度確認するか、関連するコードを表示します。はい、 'readabilityHandler'はすでに別のスレッドで呼び出しています。この関数は、タスクが完了するまで待つのではなく、何らかの問題が発生したときに提供されたクロージャを使用してフィードバックを返すことに注意してください。 – Kametrixom

+0

readabiltyHandlerについて確認していただきありがとうございます。関連するコードを更新しました。私は私の問題に貢献しているスレッドの不正な実装をしている可能性があり、おそらくあなたのソリューションとは関係がないと思う。 – user43633

関連する問題