RunLoop는 iOS와 macOS에서 애플리케이션이 이벤트를 처리하고 유휴 상태를 관리하는 중심적인 메커니즘이다. 이는 이벤트 기반 프로그래밍의 핵심으로, 프로그램이 계속 실행되는 동안 특정 작업(입력 이벤트, 타이머, 네트워크 이벤트 등)을 처리할 수 있도록 한다.
RunLoop는 크게 두 가지 구성 요소로 나눌 수 있다:
1. Input Sources (입력 소스)
NSPort
, 네트워크 소켓 등) RunLoop 실행 시작:
RunLoop는 대기 상태로 들어가 이벤트 소스나 타이머가 발생하기를 기다린다.
이벤트 발생 확인:
입력 소스나 타이머에서 이벤트가 발생하면 이를 확인한다.
핸들러 호출:
적절한 이벤트 핸들러를 호출하여 작업을 수행한다.
유휴 상태 전환:
다음 이벤트가 발생할 때까지 대기 상태로 전환한다.
메인 쓰레드의 RunLoop
메인 쓰레드는 기본적으로 RunLoop가 자동으로 관리된다. 이 RunLoop는 UIKit의 이벤트를 처리하고 애플리케이션의 UI를 업데이트하는 데 사용된다.
백그라운드 쓰레드의 RunLoop
백그라운드 쓰레드에서는 기본적으로 RunLoop가 실행되지 않으므로, 직접 RunLoop를 생성하고 실행해야 한다.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 5초마다 실행되는 Timer 추가
Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
}
@objc func timerFired() {
print("Timer fired!")
}
}
DispatchQueue.global().async {
// 현재 쓰레드에 RunLoop를 실행
let runLoop = RunLoop.current
// 10초마다 실행되는 Timer 추가
Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { timer in
print("Background timer fired!")
}
// RunLoop 실행
runLoop.run()
}
CFRunLoop
: Core Foundation 레벨의 RunLoop API로, 더 낮은 수준의 제어를 제공한다. NSRunLoop
: Foundation에서 제공하는 Objective-C 인터페이스. Swift에서도 사용 가능. RunLoop는 모드라는 개념을 사용하여 특정 이벤트 소스만 활성화한다.
대표적인 모드는 다음과 같다:
default
(기본 모드)
대부분의 일반 작업은 이 모드에서 처리됨.
UITrackingRunLoopMode
(UI 추적 모드)
스크롤 같은 UI 트래킹 이벤트를 처리할 때 사용됨.
commonModes
여러 모드에서 공통적으로 이벤트를 처리할 수 있도록 설정된 모드.
RunLoop의 각 루프 사이클은 자동으로 AutoReleasePool을 생성하고 소멸시킨다. 이는 메모리 관리를 최적화하여 반복되는 이벤트 처리에서도 메모리 누수를 방지한다.
CFRunLoopStop
이나 CFRunLoopWakeUp
을 사용.