【问题标题】:Multiple NSTasks Causing Inconsistent Output多个 NSTask 导致输出不一致
【发布时间】:2016-04-27 13:53:13
【问题描述】:

我正在开发一个 Swift 应用程序,该应用程序与外部二进制文件交互(通过 NSTask)并将输出作为字符串数组返回,对于每一行。

多次调用 executeCommand 函数时,命令开始无法返回​​预期数据。

在下面的示例 Playground 中,我正在轮询 diskutil 以获取卷名。

在调试区,我得到的第一个响应是:

  • 不适用(无文件系统)
  • Macintosh 高清
  • 无法获取音量 姓名
  • 无法获取卷名
  • 无法获取卷名

只需重新运行 Playground 即可:

  • 不适用(无文件系统)
  • 无法获取卷名
  • 无法获取卷名
  • 无法获取卷名
  • 无法获取卷名

        import Cocoa
    
    func executeCommand(launchPath: String, arguments: [String], additionalDelay: Int=0) -> [String] {
    
        let outputPipe = NSPipe()
        var outputArray = [String]()
    
        let task = NSTask()
        task.launchPath = launchPath
        task.arguments = arguments
        task.standardOutput = outputPipe
    
        outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
    
        NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification, object: outputPipe.fileHandleForReading , queue: nil) {
            notification in
    
            let output = outputPipe.fileHandleForReading.availableData
            let outputString = String(data: output, encoding: NSUTF8StringEncoding) ?? ""
    
            outputArray = outputString.componentsSeparatedByCharactersInSet(.newlineCharacterSet())
    
            outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
    
        }
    
        task.launch()
        sleep(UInt32(additionalDelay)) // Additional delay
        task.waitUntilExit()
    
        // Remove last empty line from output array.
        if outputArray.count > 0 {
            outputArray.removeLast()
        }
    
        return outputArray
    
    }
    
    
    // Example usage
    
    
    
    // Output volume name from provided disk identifier
    func volumeName(identifier: String) -> String {
        let volumeNameCommand = "/usr/sbin/diskutil info \(identifier) | awk '/Volume Name:/' | sed 's/Volume Name://g'| sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'"
        let volumeNameOutput = executeCommand("/bin/bash", arguments: ["-c", volumeNameCommand])
    
        var volumeName = "Unable to obtain volume name"
    
        if volumeNameOutput.count > 0 {
            volumeName = volumeNameOutput[0]
        }
    
        return volumeName
    }
    
    let identifiers = ["/dev/disk0","/dev/disk1","/dev/disk2","/dev/disk3","/dev/disk4"]
    
    for identifier in identifiers {
        print(volumeName(identifier))
    }
    

我真的需要一致的结果,但不明白我哪里出错了。

任何帮助将不胜感激!

【问题讨论】:

    标签: swift nstask


    【解决方案1】:

    我认为任务的异步执行导致结果不一致。下面是一个按预期工作的新函数:

    func executeCommand(launchPath: String, arguments: [String]) -> [String] {
    
        let task: NSTask = NSTask()
        let pipe: NSPipe = NSPipe()
    
        task.launchPath = launchPath
        task.arguments = arguments
        task.standardOutput = pipe
        task.launch()
        task.waitUntilExit()
    
        let handle = pipe.fileHandleForReading
        let data = handle.readDataToEndOfFile()
        let outputString = String(data: data, encoding: NSUTF8StringEncoding) ?? ""
    
        var outputArray = [String]()
        outputArray = outputString.componentsSeparatedByCharactersInSet(.newlineCharacterSet())
        return outputArray
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      • 2019-11-07
      • 2018-04-30
      • 2013-04-15
      • 1970-01-01
      • 2017-05-01
      • 2016-04-08
      相关资源
      最近更新 更多