2016-04-27 24 views
0

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

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

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

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

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

只需重新运行在操场结果:

  • 不适用(没有文件系统)
  • 无法获得卷名< - 发生了什么事的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)) 
    } 
    

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

任何帮助将不胜感激!

回答

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 

}