UIKit이 Thread Safe하지 않는 이유에서부터 시작합니다. UIKit과 같이 매우 큰 프레임워크의 모든 속성을 Thread Safe하게 설계하는 것은 비현실적입니다.
Serial Queue
에서 처리함으로써 Thread Safe하지 않음으로 발생되는 문제를 간단하게 처리할 수 있습니다.
앱을 실행하면 Cocoa Touch 에서 UIApplication 인스턴스가 메인 스레드에서 설정됩니다. 앱의 UI event 는 일반적으로 UIApplication -> UIWindow -> UIViewController -> UIView -> subviews(UILabel, UIButton 등) 와 같이 chain 으로 연결되는데, 이 responder chain 을 따라 UIApplication 으로 전달됩니다. 이러한 event chain 이 메인 스레드에서 동작하므로 responder chain 에 포함된 모든 UI 관련 동작들은 메인 스레드에서 수행되어야 합니다.
UIApplication
- UIApplication.shared 형태의 싱글턴으로 접근 가능합니다.
- 유저의 이벤트에 반응하여 앱의 초기 설정을 하는 역할.
- Background에 진입한 상태에서 추가적인 작업을 할 수 있도록 만들어주거나, 푸시알람을 받았을 때 어떤 방식으로 이를 처리할 지 등에 관한 것을 다룹니다.
Main Run Loop
Main Run Loop는 유저가 이벤트를 일으키는 이벤트들을 처리하는 프로세스로써 UIApplication 객체는 앱이 실행될 때, Main Run Loop를 실행합니다. view와 관련된 이벤트나 view의 업데이트에 활용, view와 관련되어 있기 때문에 main 쓰레드에서 실행됩니다.
모든 뷰의 변경 사항은 즉시 변경되지 않으며 현재 RunLoop의 끝에서 다시 그려집니다. 이렇게하면 애플리케이션이 모든 보기의 모든 변경 사항을 처리 할 수 있으며 모든 변경 사항이 동시에 활성화 될 수 있습니다. 이를 View Drawing Cycle
이라고합니다.
만약 (Main Thread가 아닌) BackGround Thread에서 각자의 Run-Loop로 업데이트를 하게되었을 때, View가 제멋대로 동작할 수 있습니다다. (예를 들어, 기기를 회전 했을때, 동시에 View의 Layout이 재배치되지 않고 각각 따로따로 동작할 수도 있습니다.)
iOS가 그림의 그리는 Rendering Process(CoreAnimation -> Render Server -> GPU -> Present)가 있는데, 여러 Thread에서 UI 업데이트를 하게 된다면, 각기 다른 뷰 계층 구조를 인코딩하여 렌더 서버로 전송할 것이고, 이에 따라 GPU 에 많은 렌더링 요청을 보내게 됩니다. 렌더링은 시스템 리소스가 많이 드는 작업이므로 GPU 가 이를 처리할 수 없어 심각한 문제가 발생합니다.