Вы должны сделать свою задачу асинхронной и readInBackgroundAndNotify
.
Что-то вроде этого (не проверено), он использует terminationHandler
и добавляет наблюдателя readCompletionNotification
для получения уведомлений.
var output = ""
func runCommand(cmd: String, args: String..., completion: @escaping (String, String, Int32) -> Void) {
print("running shell command")
let task = Process()
task.launchPath = cmd
task.arguments = args
let outpipe = Pipe()
task.standardOutput = outpipe
let errpipe = Pipe()
task.standardError = errpipe
task.terminationHandler = { [unowned self] returnedTask in
NotificationCenter.default.removeObserver(self,
name: FileHandle.readCompletionNotification,
object: (returnedTask.standardOutput as! Pipe).fileHandleForReading)
let status = returnedTask.terminationStatus
if status == 0 {
completion(output, "", status)
} else {
let errorData = errpipe.fileHandleForReading.readDataToEndOfFile()
let errorString = String(data:errorData, encoding: .utf8)!
completion("", errorString, status)
}
}
let outputHandle = (task.standardOutput as! Pipe).fileHandleForReading
NotificationCenter.default.addObserver(forName: FileHandle.readCompletionNotification, object: outputHandle, queue: OperationQueue.current, using: { notification in
if let data = notification.userInfo?[NSFileHandleNotificationDataItem] as? Data, !data.isEmpty {
output.append(String(data: data, encoding: . utf8)!)
} else {
task.terminate()
return
}
outputHandle.readInBackgroundAndNotify()
})
outputHandle.readInBackgroundAndNotify()
task.launch()
}
Если вы хотите распечатать данные при получении, замените output.append(String(data: data, encoding: . utf8)!)
на print(String(data: data, encoding: . utf8)!)
, и тогда вам, вероятно, также не понадобится обработчик завершения.