728x90
Main Run Loop
- main run loop는 유저로부터 모든 input 이벤트를 받고 적절한 응답을 해준다.
- 때문에 유저가 발생시킨 모든 상호작용은 event queue에 추가되고 Application object는 event queue로부터 이벤트를 하나씩 꺼내어 애플리케이션의 다른 객체들에게 전달한다.
- 즉, 애플리케이션 객체 (Application Object)는 유저로부터의 input 이벤트를 해석하고, 그에 상응하는 application 의 Core object들 안에 있는 handler를 호출한다.
- handler들은 개발자가 쓴 코드들을 호출한다.
- 위의 메서드들이 반환되면 Update Cycle이 다시 시작된다.
- Update Cycle은 View들을 배치하고 다시 그리는 역할을 한다.
순서 |
user의 input event 발생 |
Event queue에 추가 |
main run loop에서 event queue에 있는 event들을 꺼내어 Application object에게 넘김 (control을 넘김) |
Application object들에서 event를 적절한 core object들로 넘기고 handler 실행 |
handler가 리턴되면 다시 control이 main run loop로 돌아오고 update cycle 실행 |
Update Cycle
- Update Cycle은 application이 유저로부터의 모든 이벤트 핸들링 코드를 수행하고 다시 Main Run Loop로 컨트롤을 반환하는 지점이다.
- 이 지점에서 시스템이 View들을 배치(layout)하고, 그리고 (display), 제약(constraint)을 건다.
- 만약 이벤트 핸들러가 처리되는 과정에 특정 UIView에 변화가 생기면 해당 UIView는 redraw되어야 하고, 다음 Update Cycle에서 시스템이 해당 변화를 처리한다.
- iOS앱은 초당 60프레임을 보여주기 때문에 한 번의 Update Cycle은 1/60초 정도다.
- 굉장히 빠른 속도이기에 User는 UI와 상호작용 사이의 차이를 인지하지 못한다.
- 하지만 이벤트가 처리되는 시점과 실제로 View가 다시 그려지는 시점엔 차이가 있기 때문에, 만약 우리가 View의 마지막 layout content에 대해 계산을 해야한다면, 예전 정보를 가지고 조작할 수 있는 가능성이 생긴다.
Layout
- UIView의 크기, 위치를 의미한다.
layoutSubviews()
- View와 자식뷰들의 위치, 크기를 재조정하는 메서드이다.
- 재귀적으로 모든 자식 뷰의 layoutSubviews까지 호출하기 때문에 부하가 큰 메서드이다.
- 그렇기에 직접 호출은 금지되어있다.
- 시스템은 View의 frame을 다시 계산해야할 때 layoutSubview를 호출하기 때문에 layoutSubviews를 오버라이딩해서 frame이나 특정 위치, 크기를 조절할 수 있다.
- ViewController에서는 layoutSubviews가 완료되면 viewDidLayoutSubviews가 호출된다.
- 레이아웃의 크기, 위치와 관련된 로직을 View에선 layoutSubviews, ViewController에서는 viewDidLayoutSubviews에서 호출하는 것이 오래된 레이아웃, 위치 변수를 계산에 이용하는 실수를 막는 방법이다.
자동으로 layoutSubviews()가 호출되는 경우
- View를 Resizing
- SubView 추가
- UIScrollView를 스크롤할 때, UIScrollView와 부모뷰가 layoutSubviews호출
- Device 회전
- View의 constraint 변경
수동으로 layotuSubviews()를 호출하는 방법
setNeedsLayout()
- layoutSubviews를 가장 적은 부하로 호출할 수 있는 메서드
- 시스템에게 해당 View의 layout이 다시 계산되어야함을 알려준다.
- setNeedsLayout은 호출 즉시 반환되고, 직접 레이아웃을 업데이트 하진 않는다.
- 다음 Update Cycle에서 View와 자식 뷰들의 layoutSubviews가 호출되게 한다.
layoutIfNeeded()
- 만약 View가 layout이 재조정되어야 한다면, 즉시 layoutSubviews를 호출한다.
- 만약 setNeedsLayout을 호출한 직후, 혹은 자동으로 layoutSubviews를 호출해주는 방법을 쓴 이후에 layoutIfNeeded를 호출한다면 즉시 layoutSubviews가 호출된다.
- 반대로 재조정될 이유가 없다면 호출되지 않는다.
- setNeedsLayout과 다르게 layout 및 자식 뷰들을 즉시 다시 그리는 작업을 메서드가 반환되기 전에 실행한다.
- Costraint를 이용한 애니메이션을 쓰는 상황에서 유용하다.
- 애니메이션 시작전에 layoutIfNeeded를 호출해서 미리 레이아웃을 업데이트 하고 Animation 클로저 안에서 다시 layoutIfNeeded를 호출해서 애니메이션을 실행할 수 있다.
Display
- View의 속성들 중 크기, 위치, 자식 뷰들에 대한 정보를 갖지 않는 속성들을 포함한다.
- 색, 텍스트, 이미지, Core Graphic 그리기 등
- Layout과정과 마찬가지로 시스템이 자동으로 업데이트하게 하는 방식, 수동으로 업데이트 하는 방식이 존재한다.
draw()
- Layout업데이트 과정의 layoutSubviews와 동일한 역할
- 차이점은 자식뷰들의 draw를 호출하지는 않는다.
- 직접 호출은 금지
setNeedsDisplay
- setNeedsLayout과 유사하다.
- 내부 dirty플래그를 활성화하고, 다음 Update Cycle에서 해당 플래그가 활성화된 View들의 draw를 호출해서 다시 그리게 한다.
- 일부분만 다시 그려지길 원한다면 파라미터로 rect를 전달할 수 있다.
- 대부분의 경우, 우리가 명시적으로 이 메서드를 호출하지 않아도 Update Cycle에 다시 그려진다.
- 하지만 만약 UI컴포넌트에 직접적으로 연관되어 있지 않지만 매 Update Cycle마다 다시 뷰를 그리게 해야하는 속성이 있다면, didSet안에서 setNeedsDisplay를 명시적으로 호출해줄 수 있다.
Constraints
- Auto Layout에서는 Layout하고 Draw하는 것에 대해 3단계의 과정이 필요하다.
- Constraint업데이트: 시스템이 View에 필요한 Constraints를 계산하고 설정한다.
- Layout단계: 레이아웃 엔진이 View들의 frame, 자식 뷰들의 frame을 계산하고 배치
- Display단계: View들의 컨텐츠를 다시 그린다.
updateConstraints
- layoutSubviews, draw와 같이 오직 오버라이딩 되어야 하며 명시적으로 호출되면 안된다.
- 보통 동적으로 변해야 하는 Constraint들을 구현할 때 updateConstraints안에 구현한다.
- 정적인 Constraints는 InterfaceBuilder, View의 생성자, viewDidLoad에서 정의한다.
자동으로 다음 UpdateCycle에서 updateConstraints 호출하게 하는 경우
- Constraints를 활성화 / 비활성화하는 경우
- Constrinats의 priority, constant를 변경한 경우
- View 계층에서 View를 삭제한 경우
수동으로 (명시적으로) updateConstraints를 호출하게 하는 경우
setNeedsUpdateConstraints
- setNeedsLayout, setNeedsDisplay와 유사한 역할
- 다음 Update Cycle에서 updateConstraints호출 보장
updateConstraintsIfNeeded
- layoutIfNeeded와 유사
- 하지만 auto layout을 사용하는 뷰에만 유효
- Constraint Update 플래그를 검사해서 업데이트 되어야 한다면 updateConstraints를 즉시 호출한다.
- 해당 플래그는 자동 설정, setNeedsUpdateConstraints, invalidateIntrinsicContentSize를 통해 설정 가능하다.
invalidateIntrinsicContentSize
- auto layout을 사용하는 일부 View들은 intrinsicContentSize속성을 가지고 있고 이것은 View가 가지고 있는 Content의 크기이다.
- invalidateIntrinsicContentSize를 호출하면 View의 intrinsicContentSize가 다음 Update Cycle에서 재계산되어야함을 알리는 플래그를 활성화한다.
Layout, Display, Constraints의 메서드들
Update Cycle에서 메서드들이 호출되는 모습
728x90
'iOS > 설명' 카테고리의 다른 글
[iOS] Bundle (0) | 2022.04.22 |
---|---|
[iOS] 앱 terminate되게 하는 법 (0) | 2022.04.22 |
[iOS] autoresizingMask (0) | 2022.04.16 |
[iOS] KVO (Key-Value Observing) (0) | 2022.04.16 |
[iOS] APNs 이용해서 Push 보내기 (0) | 2022.04.09 |
댓글