https://babbab2.tistory.com/68
iOS) 런 루프(RunLoop) 이해하기
안녕하세요 :) 소들입니다 오늘은 RunLoop라는 것에대해 공부를 해볼 건데여 음... 내용이 좀 어려울 수도 있어여!! 저도 오랜만에 다뤄서 완전히 이해하고 쓰는 내용이 아니라... (한 1년 전에 공부
babbab2.tistory.com
https://developer.apple.com/documentation/foundation/runloop
RunLoop | Apple Developer Documentation
The programmatic interface to objects that manage input sources.
developer.apple.com
RunLoop
- RunLoop은 window system의 마우스, 키보드나 port에서 오는 event들을 처리하는 object이다.
- 또한 Timer event도 처리한다.
- RunLoop입장에선 Timer는 input이 아니지만 특별한 타입으로써 취급한다.
- System은 main thread를 포함해서 기본적으로 모든 thread마다 RunLoop을 생성한다.
- 다만 main thread를 제외하고 RunLoop이 처음부터 생성되어있는 것은 아니고 RunLoop.current로 현재 스레드의 RunLoop에 접근시도 시 RunLoop이 존재하지 않으면 생성한다.
- Main thread의 RunLoop은 앱 실행 시, UIApplicationMain()함수 내부에서 초기화 된다.
- 주의해야될 건 RunLoop은 Thread safety하지 않기 때문에 반드시 현재 thread의 context내에서만 사용해야한다.

Main RunLoop

- Main RunLoop은 앱 실행 시 생성과 loop의 실행이 자동적으로 진행된다.
- Device에서 일어나는 user의 이벤트를 OS, Port를 거쳐서 Event Queue에 받은 뒤 UIApplication을 시작으로하는 UIResponder chain에 넘겨줘서 처리하도록 한다.
Worker thread에서 Timer가 동작하지 않는 이유
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async(execute: {
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { _ in
print("timer")
})
})
}
위 코드를 실행 시 Timer의 동작은 제대로 실행되지 않는다.
그 이유는 Worker thread의 RunLoop은 현재 생성되어있지도 않고, loop가 돌고 있는 상황도 아니기 때문

때문에 아래와 같이 명시적으로 run을 호출해줘야 Input source로부터 Event를 받아들이고 처리하기 시작한다.
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async(execute: {
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { _ in
print("timer")
})
RunLoop.current.run()
})
}
Appendix
Timer() vs Timer.scheduledTimer()

Timer()는 타이머 객체를 생성만하고 RunLoop에 붙이지는 않는다. 때문에 RunLoop에 붙이기 전까진 Timer가 동작하지 않는다.
때문에 Timer() 사용 시 아래와 같이 current RunLoop에 명시적으로 Timer를 추가해줘야한다.
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async(execute: {
let timer = Timer(timeInterval: 0.5, repeats: true, block: { _ in
print("timer")
})
RunLoop.current.add(timer, forMode: .common)
RunLoop.current.run()
})
}
반면 scheduledTimer는 Timer 객체 생성 후 current RunLoop에 default mode로 추가하는 작업까지 해준다. 때문에 add()함수를 호출해서 timer를 명시적으로 붙여주지 않아도 Timer가 동작한다.
'iOS > 설명' 카테고리의 다른 글
[iOS] '==' vs '===' (0) | 2024.03.17 |
---|---|
[iOS] OOP와 POP는 어떤 경우에 써야 할까 (고찰) (0) | 2024.03.17 |
[iOS] High performance based drawing (0) | 2024.02.24 |
[iOS] Mirror Struct (0) | 2024.02.24 |
[iOS] iOS Webview에서 텍스트 복사하는법 (0) | 2023.07.15 |
댓글