多个NSTasks导致输出不一致

时间:2016-04-27 13:53:13

标签: swift nstask

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

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

在下面的Playground示例中,我为卷名称轮询diskutil。

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

  • 不适用(无文件系统)
  • Macintosh HD
  • 无法获得音量 名称
  • 无法获取卷名
  • 无法获取卷名

只需重新运行Playground结果:

  • 不适用(无文件系统)
  • 无法获取卷名< - Macintosh HD发生了什么变化?
  • 无法获取卷名
  • 无法获取卷名
  • 无法获取卷名

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

我确实需要一致的结果,但不知道我哪里出错了。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

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

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

}