Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<3주차> UIKit 클래스들을 다룰 때 꼭 처리해야하는 애플리케이션 쓰레드 이름은 무엇인가? #16

Closed
namsoo5 opened this issue Nov 13, 2020 · 7 comments

Comments

@namsoo5
Copy link
Collaborator

namsoo5 commented Nov 13, 2020

No description provided.

@namsoo5
Copy link
Collaborator Author

namsoo5 commented Nov 17, 2020

Main Thread

이유

UIApplication의 인스턴스가 main thread에 붙고(attach)
이 UIApplication은 앱을 시작할 때 인스턴스화 되는 앱의 첫번째 부분이고
앱의 run loop를 포함하여 main event loop를 설정하고 event처리를 시작함
앱의 main event loop는 touch, gesture등의 모든 UI event를 수신함

앱의 UI event는 일반적으로 UIApplication -> UIWindow -> UIViewController -> UIView -> subviews (UIButton 등)와 같이 chain으로 연결되는데, 이 responder chain을 따라 UIResponder로 전달

Responder는 버튼 누르기, 탭, pinch, 확대/축소, 스와이프 등의 이벤트를 UI 변경사항으로 처리합니다. 따라서 이러한 일련의 event chain이 UIKit의 main thread에서 작동하는 이유임.
label이나 View는 UIApplication의 자식이므로, 모든 이런 UI작업은 main thread의 “일부”라고 할 수 있음.
그래서 모든 이벤트는 main thread의 일부가 되며, main thread에서 처리해야합니다

UIKit 정의

Use UIKit classes only from your app’s main thread or main dispatch queue, unless otherwise indicated. This restriction particularly applies to classes derived from UIResponder or that involve manipulating your app’s user interface in any way.

별도의 표시가 없는 한, 앱의 main 스레드 또는 main 디스패치 대기열에서만 UIKit 클래스를 사용하십시오.
이 제한은 특히 UIResponder에서 파생되거나 어떤 방식으로든 앱의 사용자 인터페이스를 조작하는 것과 관련된 클래스에 적용됌.

UIKit는 thread safe하지않음
프레임워크 안에 많은기능들을 내포하고있기때문에 safe하게 만들시 성능이 좋지않음

참조블로그 제드님

@khyunjiee
Copy link
Member

khyunjiee commented Nov 20, 2020

Main Thread

Cocoa Touch 어플리케이션은 UIApplication의 인스턴스가 main thread에 attach된다.
main threadUIApplication으로부터 만들어지고, UIApplication은 앱이 처음 시작될 때 인스턴스화 되는 앱의 첫 시작 부분이다.
UIApplication은 어플리케이션 run loop를 포함한 main event loop를 세팅하고이벤트 처리를 한다.
어플리케이션의 main event loop는 touch, gesture같은 모든 UI 이벤트들을 받는다.

어플리케이션 UI 이벤트는 UIApplication->UIWindow->UIViewController->UIView->subviews(UIButton,etc.) 와 같은 response chain에 따라 UIResponse에 전달된다.
UIResponder는 버튼 press, tap,확대 축소, swipe 등의 UI 변경으로 인식되는 이벤트를 다룬다.
이러한 이벤트들이 main thread에서 발생하므로 응답자가 포함된 UIKit 프레임워크는 main thread에서 작동해야 한다.


왜 main.sync는 동작하지 않을까?

main queue는 하나의 task가 끝나야 다음 task를 실행하는 serial queue이다.
그리고 sync는 task가 끝날 때까지 다음 task를 실행하지 않고 queue를 block한 뒤 task가 완료될 때까지 기다린다.
main.sync가 되면 queue가 block 상태가 되고 task가 끝날 때까지 기다린다. 하지만 main queue는 이미 block 상태이므로 task를 실행할 수 없다. deadlock

하지만 직접 serial queue를 만들어서 sync로 처리하면 잘 작동하는 것을 볼 수 있다.

왜 main queue만 작동되지 않을까?
main thread는 thread-safe하지 않기 때문이다.
모든 UIKit 관련 작업들이 thread-safe는 아니다. 일부분은 safe하고 일부분은 safe하지 않다.

thread-safe는 말 그대로 thread로부터 보호하는 것이다. main thread가 thread-safe하지 않는 것은 애플의 디자인 결정이라고 한다..
thread-safe로 thread를 만들면 성능 면에서 별로 좋지 않고, 오버 헤드가 커지기 때문이다.

결론적으로 UIKit이 main thread에 attach 되어 있으면 concurrent 프로그램을 작성하고 UIKit을 사용하는 것이 쉽다.

@iJoom
Copy link
Collaborator

iJoom commented Nov 20, 2020

UIkit은 항상 Main Thread 에서 작동되어져야합니다.

This restriction particularly applies to classes derived from UIResponder or that involve manipulating your app’s user interface in any way.
이러한 제한은 특히 UIResponder에서 파생되거나, 다양한 방법으로 앱의 사용자 인터페이스를 조작하는 것과 관련된 클래스에 적용됩니다. EX) UIApplication -> UIWindow -> UIViewController -> UIView -> Subviews

Cocoa Touch 앱에서 UIApplication의 인스턴스가 main thread에 Attach되기 때문이며, UIApplication은 앱을 시작할 때 인스턴스화 되는 앱의 첫번째 부분이다.
앱의 Run Loop를 포함하여 Main event loop를 설정하고 event처리를 시작합니다. 앱의 main event loop는 touch, gesture등의 모든 UI event를 수신한다. UIApplication -> UIWindow -> UIViewController -> UIView -> Subviews

이러한 다양한 터치 이벤트와 gesture를 사용자에게서 항상 즉각적으로 받아내고, 메인 루프를 돌면서 UI적 요소를 그릴려면 성능도 좋아야 하며 오버 헤드(처리시간)도 작아야 한다. (그만큼 처리해야할 연산과 event가 많으므로) 따라서 애플은 Main Thread에서 safe하지 않게 함으로서 이러한 구조를 디자인 했다. (쓰레드가 safe하면 성능과 오버헤드가 증가)

@iJoom iJoom added the 인준 label Nov 20, 2020
@5anniversary
Copy link
Collaborator

스크린샷 2020-11-20 오후 2 47 56

UIKit은 앱의 메인 스래드 혹은 메인 디스패치큐에서만 사용이 가능!!

위의 제한은!!! UIResponder에서 파생되거나 어떤 방식으로든 앱의 사용자 인터페이스를 조작하는 것과 관련된 클래스에 적용됨!!

여기서 UIResponder라 함은???

UIApplication, UIViewController, UIView(UIWindow 포함) ~~등등 우리가 UIKit에서 사용하는 많은 것들을 포함하는 응답 객체!!

(사용자에게 보여주는 객체라고 생각하면 편할 듯...?)

@Juhyeoklee
Copy link
Collaborator

Main Thread

Cocoa Touch 앱에서는 UIApplication의 인스턴스가 main thread에 붙기 때문입니다. UIApplication은 앱을 시작할 때 인스턴스화 되는 앱의 첫번째 부분인데 앱의 run loop를 포함하여 main event loop를 설정하고 event 처리를 시작합니다. 앱의 main even loop는 touch, gesture등의 모든 UI Event를 수신합니다.

앱의 UI Event는 일반적으로 UIApplication -> UIWindow -> UIViewController -> UIView -> subviews 와 같이 chain으로 UIResponder로 전달됩니다. Responder는 버튼 누르기, 탭, pinch, 확대/축소, 스와이프 등의 이벤트를 UI 변경사항으로 처리합니다.

따라서 이러한 일련의 event chain이 UIKit이 main thread에서 작동하는 이유입니다.

@elesahich
Copy link
Collaborator

답 : Main Thread.

https://developer.apple.com/documentation/uikit/1622933-uiapplicationmain
https://stackoverflow.com/questions/18467114/why-must-uikit-operations-be-performed-on-the-main-thread 참조

UIApplication(), 즉 애플리케이션 인스턴스는 CocoaTouch의 진입함수인 UIApplication()에 의해 생성되므로 메인 스레드에 붙여집니다(attach). 이는 메인 스레드를 사용하는 메인 이벤트 루프를 셋업하며, 이벤트 처리를 시작합니다. 메인 이벤트 루프는 모든 UI 이벤트 를 수신합니다. (NSObject(class), UIResponder 객체)

또, UI 이벤트는 일반적으로 UIApplication-> UIWindow-> UIViewController-> UIView-> subviews (UIButton 등)와 같은 응답자 체인을 따라 UIResponder에 전달됩니다. Responder는 UI의 변경으로 번역되는 버튼 누름, 탭, 핀치 줌, 스 와이프 등과 같은 이벤트를 처리합니다. 따라서 이러한 일련의 이벤트가 메인 스레드에서 발생하는 것을 볼 수 있으므로 UIKit, 응답자를 포함하는 프레임 워크가 메인 스레드에서 작동해야합니다.

UIKit 문서를 보자
https://developer.apple.com/documentation/uikit

아래쯤에 누가봐도 중요해보이는 노란색 문장을 읽어보자아
Use UIKit classes only from your app’s main thread or main dispatch queue, unless otherwise indicated. This restriction particularly applies to classes derived from UIResponder or that involve manipulating your app’s user interface in any way.

만약 다르게 명시되지 않는다면 UIKit은 당신의 앱의 메인 디스패치 큐에서만 사용하세염
이 제한은 특히 UIResponder의 반응에서 파생되거나*(derived), 어떤식으로든 유저 인터페이스를 조작하는것에 관련이 있습니다

@elesahich elesahich added the 승호 승호 label Nov 20, 2020
@choidam
Copy link
Member

choidam commented Nov 20, 2020

Main Thread

UIKit은 Thread-safe 하지 않습니다. 그래서 모든 처리를 Serial 하게 처리해야 합니다. 그래서 UI는 Main Thread 에서 synchronously 하게 동작해야 합니다.

당신이해야 할 일은 항상 UIKit에 대한 호출이 항상 main thread에서 이루어 지도록하는 것입니다. 따라서 UIKit 객체가 main thread에서 액세스되어야한다는 사실은, 성능에 유리하도록 한 apple의 디자인 결정입니다

그리고 많은 background thread 에서 UI를 update 하게 되면 각각의 스레드가 서로 다른 rendering 정보를 처리하기 때문에 많은 transaction 을 처리해야 합니다. 이러한 rendering 은 GPU가 처리할 수 없는 transaction 의 한계를 넘게 됩니다.

앱의 UI event는 일반적으로 UIApplication -> UIWindow -> UIViewController -> UIView -> subviews (UIButton 등)와 같이 chain으로 연결되는데, 이 responder chain을 따라 UIResponder로 전달됩니다. Responder는 버튼 누르기, 탭, pinch, 확대/축소, 스와이프 등의 이벤트를 UI 변경사항으로 처리합니다. 따라서 이러한 일련의 event chain이 UIKit의 main thread에서 작동하는 이유입니다.

참고하면 좋은 링크

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment