2016-08-19 8 views
2

変数 'a'が作成されています。たとえば、デスクトップ上のテキストファイルの値です。私はデータを連続的に読んで、私のアプリケーションに 'a'の値を表示したい。Swift:ユーザー入力なしでテキストファイルまたはサーバーから連続してデータを読み取る方法

テキストファイルから値を変更しても、アプリケーションに自動的に反映されるはずです。

提案がありますか?

私はあなたがファイルを監視するために、GCDの派遣ソースを使用することができスウィフト2.2

+0

このファイルを正しく開くと、これは自動的に発生します。 NSDocumentは、ファイルが変更されたために再読み込みする必要があることを伝えます。 – matt

+0

ここをクリックしてください:http://codekea.com/2EgRdM8Mmb5R/real-time-nstask-output-to-nstextview-with-swift.html – Woodstock

答えて

1

を使用しています。以下は、ファイルを監視し、更新のたびにファイルの内容でNSTextViewを更新する簡単な例です。

class ViewController: NSViewController { 
    @IBOutlet var textView: NSTextView! 

    // Create a dispatch_source_t to monitor the file 
    func dispatchSoureForFile(at path: String) -> dispatch_source_t? { 
     let fileHandle = open(path.cStringUsingEncoding(NSUTF8StringEncoding)!, O_RDONLY) 

     // Cannot open file 
     guard fileHandle != -1 else { 
      return nil 
     } 

     // The queue where the event handler will execute. Don't set to the main queue 
     let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

     // The events we are interested in 
     let mask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND 

     return dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, UInt(fileHandle), mask, queue) 
    } 

    // The function to use for monitoring a file 
    func startMonitoringFile(at path: String) { 
     guard let dispatchSource = dispatchSoureForFile(at: path) else { 
      print("Cannot create dispatch source to monitor file at '\(path)'") 
      return 
     } 

     let eventHandler = { 
      let data = dispatch_source_get_data(dispatchSource) 

      // Tell what change happened to the file. Delete it if you want 
      if data & DISPATCH_VNODE_WRITE != 0 { 
       print("File is written to") 
      } 
      if data & DISPATCH_VNODE_EXTEND != 0 { 
       print("File is extended to") 
      } 
      if data & DISPATCH_VNODE_DELETE != 0 { 
       print("File is deleted") 
      } 

      // Sometimes the old version of the file is deleted before the new version is written 
      // to disk. This happens when you call `writeToFile(_, atomically: true)` for example. 
      // In that case, we want to stop monitoring at the old node and start at the new node 
      if data & DISPATCH_VNODE_DELETE == 1 { 
       dispatch_source_cancel(dispatchSource) 
       self.startMonitoringFile(at: path) 
       return 
      } 

      // Always update the GUI from the main queue 
      let fileContent = try! String(contentsOfFile: path) 
      dispatch_async(dispatch_get_main_queue()) { 
       self.textView.string = fileContent 
      } 
     } 

     // When we stop monitoring a vnode, close the file handle 
     let cancelHandler = { 
      let fileHandle = dispatch_source_get_handle(dispatchSource) 
      close(Int32(fileHandle)) 
     } 

     dispatch_source_set_registration_handler(dispatchSource, eventHandler) 
     dispatch_source_set_event_handler(dispatchSource, eventHandler) 
     dispatch_source_set_cancel_handler(dispatchSource, cancelHandler) 
     dispatch_resume(dispatchSource) 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.startMonitoringFile(at: "/path/to/file.txt") 
    } 
} 

DISPATCH_VNODE_EXTENDイベントをトリガーするために、あなたはターミナルでこれを試すことができます。

echo "Hello world" >> /path/to/file.txt 
+0

ありがとう、あなたにチェックして戻ってきます。 – Coding4Life

1

私は非常によく似たユースケースのために(スウィフト3.xの中で)動作するように次のコードを得ることができました。それが役に立てば幸い。

override func viewDidLoad() { 
    super.viewDidLoad() 

    NotificationCenter.default.addObserver(
     self, 
     selector: #selector(ViewController.commandOutputNotification(_:)), 
     name: NSNotification.Name.NSFileHandleDataAvailable, 
     object: nil) 

    self.startTasks() 
} 

func startTasks() { 
    self.task = Process() 
    self.task!.terminationHandler = self.commandTerminationHandler 
    let argumentsString = "tail -n 1 -f /path/to/file/file.log" 

    self.task!.launchPath = "/bin/sh" 
    self.task!.arguments = ["-c", argumentsString] 

    let pipe = Pipe() 

    task!.standardOutput = pipe 
    task!.standardError = pipe 

    pipe.fileHandleForReading.waitForDataInBackgroundAndNotify() 

    task!.launch() 
} 

func commandTerminationHandler(_ task: Process) -> Void { 
    // TODO: finish this 
} 

func commandOutputNotification(_ notification: Notification) { 
    let fileHandle = notification.object as! FileHandle 
    let data = fileHandle.availableData 

    if data.count > 0 { 
     processLogData(data:(String.init(data: data, encoding: String.Encoding.utf8))) 
     fileHandle.waitForDataInBackgroundAndNotify() 
    } 
} 

func processLogData(data:String?) { 
    // Handle data String 
} 
関連する問題