: RunLoop 객체는 입력 소스를 처리하는 이벤트 처리 루프.
: 스레드 의 외부 입력 소스(Input Source) 및 타이머(Timer) 처리
스레드는 모두 각자의 RunLoop를 가질 수 있다 (O)
스레드를 생성할 때 RunLoop가 자동으로 생성된다 (O)
스레드의 RunLoop 는 자동으로 실행된다 (X)
RunLoop는 자동 생성되긴 하지만 자동으로 실행되진 않음 - 개발자가 RunLoop 실행을 관리해 주어야 한다.
단, Main RunLoop 는 예외 - 메인 스레드는 애플리케이션이 실행될 때, 프레임워크 차원에서 자동으로 RunLoop를 설정하고 실행한다. 이를 Main RunLoop라고 한다.
따라서 내가 생성한 스레드가 '외부 입력 소스'나 'Timer' 를 처리해야 한다면, RunLoop를 얻어서 실행시켜 주어야 한다.
let runLoop = RunLoop.current
와 같이 현재 스레드의 RunLoop를 얻는다.run()
을 통해 실행시켜 준다.RunLoop를 직접 사용하는 경우는 스레드를 직접 만들어 다음과 같은 작업을 할 때이다.
RunLoop는 루프 수행 시 2가지 종류의 Event Source 를 수신한다 - Input Source, Timer
RunLoop는 한 번의 루프 동안 스레드에 도착한 이벤트를 받고, 이에 대한 핸들러를 수행하는 객체이다.
✅ RunLoop는 이름이 '루프'이긴 하지만, 스스로 반복 실행을 하지는 않는다. 한 번 Event Source를 읽고 전달하면 이후 '대기'상태가 된다. 그래서 다음 이벤트가 발생해도 RunLoop 가 대기 상태이기 때문에 이벤트를 받을 수 없다. - 따라서 스레드 내에서 개발자가 명시적으로 for
, while
등을 통해 RunLoop를 반복 실행시켜주어야 한다.
RunLoop를 실행을 위해 4가지 메서드가 있다.
*보통은 run(until:)
만 사용한다.
func run()
run()
실행 전 선언된 모든 Input Source 의 데이터를 처리func run(mode: RunLoop.Mode, before: Date) -> Bool
func run(until: Date)
지정 날짜까지 루프를 실행하고, 그 기간 동안 루프는 부착된 모든 Input Source 들의 데이터를 처리한다.
보통 RunLoop를 반복 실행할 때 이 메서드를 사용 - RunLoop를 실행시키고, 원하는 만큼 반복
예시 코드
DispatchQueue.main.async {
var isRunning = true
let runLoop = RunLoop.current
Timer.scheduledTimer(withTimeInterval: 3, repeats: true) {_ in
print("Beep!")
}
while isRunning {
runLoop.run(until: Date().addingTimeInterval(1))
}
}
func acceptInput(forMode: RunLoop.Mode, before: Date)