2016-04-27 58 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 

}