파이썬의 Subprocess 모듈을 사용하는 것과 비슷하게, Objective-C에서는 NSTask
를 사용하여 프로세스 내에서 다른 외부 프로세스를 실행할 수 있다. Swift로 넘어오면서 NSTask는 브릿징을 통해서 그대로 사용 가능했지만, API를 좀 더 모던하게 개선한 Process라는 별도의 클래스가 새롭게 정의되었다. Process를 사용하여 외부 프로세스의 출력 결과를 가져오는 방식은 .standardOutput
프로퍼티를 이용하여 Pipe를 통해 데이터를 받을 수 있다.
외부 프로세스가 실행되는 동안 .waitUntilExit()
를 통해서 프로세스 흐름을 블럭하고 기다리는 방법도 있지만, GUI를 사용하는 경우에는 UI가 멈춰버리기 때문에 .terminationHandler
를 사용하여 서브 프로세스 실행이 완료되었을 때, 런루프가 지정한 적절한 시점에 콜백을 실행할 수도 있다.
파이프를 통한 결과 획득
Process
객체를 생성하고 실행할 때 standardOutput
, standardInput
등의 속성에 Pipe
객체를 지정해주면, 해당 프로세스의 표준 입출력을 프로그램에서 사용할 수 있다. 프로세스는 생성한 후에 launchPath
와 arguments
를 지정하여 실행할 명령의 경로와 인자를 전달한다. 그런다음 실행(launch
)한 후에 .waitUntilExit()
를 통해서 해당 프로세스가 종료될때까지 기다렸다가 파이프에 들어온 데이터를 읽으면 된다.
import Foundation
let task = Process()
let pipe = Pipe()
task.launchPath = "/bin/ls"
task.standardOutput = pipe
try? task.run()
task.waitUntilExit()
// FileHandle.availableData: Data (Data? 타입이 아님)
if case let data = pipe.fileHandleForReading.availableData, data.count > 0 {
String(data:data, encoding:.utf8)?.split(separator:"\n").forEach{ print($0) }
}
파이프를 한 번 읽고나면 파이프는 닫히기 때문에, waitUntilExit()
를 호출해서 프로세스가 완전히 끝날 때까지 대기해야한다. GUI에서는 이 메소드가 블럭하면서 UI가 프리징될 수 있기 때문에, 핸들러를 통한 처리 방식을 사용할 것이 권장된다.
더 보기 »(Swift) Process를 이용한 외부 프로세스 이용