study record
[iOS] iOS 레이아웃 사이클 본문
레이아웃 사이클
iOS 레이아웃 사이클은 세가지 단계로 이루어진다.
1. 제약 조건 (Constraints)
- 오토레이아웃의 제약 조건 갱신
- 제약 조건은 뷰를 실제로 배치하는데에는 영향을 주지 않는다.
- 제약 조건의 갱신은 뷰 계층구조에서 하위뷰에서 상위뷰의 순서로 이루어진다.
2. 레이아웃 (Layout)
- 제약 조건을 바탕으로 레이아웃을 갱신한다.
- 레이아웃은 구체적인 뷰의 프레임이다.
- 이 단계에서 뷰의 Center와 Bounds를 결정한다.
- 레이아웃의 갱신은 뷰 계층구조에서 상위뷰에서 하위뷰의 순서로 이루어진다.
3. 그리기 (Draw)
- 레이아웃 단계에서 구한 프레임을 CoreGraphics를 사용하여 화면에 그린다.
뷰컨트롤러의 레이아웃 사이클
1. loadView()
IB에서 구성한 view들이 인스턴스화 되는 단계
2. viewDidLoad()
VC의 view가 생성된 이후 호출된다.
IB에서 구성한 SubView들이 인스턴스로 존재한다.
3. viewWillAppear()
view를 그리기 전 호출된다.
view의 updateConstraints(), intrinsicContentSize()가 호출된다.
4. updateViewConstraint()
Constraint를 업데이트하는 단계이다.
소유하고 있는 view들이 업데이트가 필요하면 시스템에 의해 호출된다.
5. viewWillLayoutSubviews()
Subview들의 레이아웃 갱신 전 호출된다.
view의 layoutSubviews()가 호출된다.
6. viewDidLayoutSubviews()
Subview들의 레이아웃 갱신 후 호출된다.
view의 drawRect()가 호출된다.
7. viewDidAppear()
view가 모두 그려진 후 호출된다.
updateConstraints
뷰의 제약 조건을 갱신한다. 이 메서드를 재정의하면 제약 조건의 변경 사항을 최적화할 수 있다.
이 함수는 직접 호출하면 안 된다. 시스템이 호출해준다.
시스템에 제약 조건 갱신을 요청하기 위해서는 setNeedsUpdateConstraints 메서드를 호출해야 한다. setNeedsUpdateConstraints 메서드를 호출하면 뷰의 제약 조건을 갱신해야한다는 플래그를 표시하게 된다. 시스템은 실행루프가 끝나고 다음 실행 루프를 실행할 때 뷰의 플래그를 보고 한 번에 모든 제약 조건을 갱신한다. 따라서 호출하는 순간에 제약 조건이 바로 갱신되는 것이 아니라 다음 실행루프에 한번만 갱신하게 된다. 한 번의 실행루프에서 갱신이 여러 번 일어나면 비효율적이기 때문이다.
updateConstraintsIfNeeded
시스템은 제약의 갱신이 필요할 때 이 메서드를 호출하여 뷰와 하위 뷰의 제약조건이 갱신되도록 합니다. updateConstraintsIfNeeded는 새로운 제약 조건을 바로 적용해야할 경우 개발자가 수동으로 호출할 수 있습니다. 이 메서드는 다음 실행루프가 아닌, 호출된 순간에 제약조건을 갱신합니다.
이 메서드는 재정의하면 안 된다.
레이아웃
layoutSubviews
하위 뷰를 배치한다. 하위 클래스는 하위 뷰의 더 정확한 레이아웃을 조정하기 위해 필요한 경우 이 메서드를 재정의할 수 있다. 하위 뷰의 오토리사이징 및 오토레이아웃이 원하는 동작을 제공하지 않는 경우에만 이 방법을 재정의해야 합니다. 이 메서드에서 하위뷰의 frame을 직접 설정할 수 있습니다.
layoutSubviews는 UIView의 메서드로 View와 자식 View들의 위치와 크기를 재조정한다. 이는 현재 뷰와 모든 자식 뷰의 위치와 크기를 제공한다. 이 메서드는 재귀적으로 모든 자식 뷰의 layoutSubviews까지 호출해야하므로 실행 시에 부하가 큰 메서드이다.
레이아웃의 갱신은 상위뷰에서 하위뷰의 순서로 이루어지므로 상위뷰의 layoutSubviews메서드를 가장 먼저 호출해야 한다. 이 함수는 직접 호출하면 안 된다.
다음의 경우에는 시스템이 layoutSubview를 호출한다.
- View를 Resizing
- SubView를 추가
- UIScrollView를 스크롤할 때, UIScrollView와 그것의 부모뷰에 layoutSubviews가 호출
- Device를 회전(orientation change)
- View의 Constraint를 변경
updateConstraints메서드와 같이 강제로 레이아웃을 갱신하고자 하면 setNeedsLayout 메서드를 호출하면 다음 실행루프에서 레이아웃이 갱신된다. 즉시 레이아웃을 갱신하고 싶으면 layoutIfNeeded 메서드를 호출할 수 있다. layoutIfNeeded는 즉시 layoutSubview를 호출해버린다.
requiresConstraintBasedLayout
뷰의 레이아웃이 제약 조건에 의존하는지 여부를 나타내는 Bool타입 연산 프로퍼티이다. 뷰가 제약 조건 기반 레이아웃을 사용하고 제대로 작동할 경우 true를 반환한다. 커스텀 뷰이고, 오토리사이징을 사용하여 올바른 레이아웃을 조정할 수 없는 경우 이 프로퍼티를 true로 재정의해야 한다.
그리기 Draw
draw
Core Graphics 및 UIKit 같은 기술을 사용하여 뷰의 내용을 그리는 하위 클래스는 이 메서드를 재정의하고 해당 드로잉 코드를 구현해야 한다. 이 외의는 메서드를 재정의 할 필요가 없다. 예를들어, 뷰가 배경색만 표시하거나, 기본 레이어를 사용하여 직접 컨텐츠를 설정하는 경우에는 재정의 할 필요가 없다. 이 메서드는 뷰를 다시 그리는데만 사용되어야 하며, 레이아웃을 조정하거나 데이터를 조작하면 안 된다.
이 메서드는 뷰가 처음 표시될 때, 또는 뷰의 보이는 부분을 무효화하는 이벤트가 발생될 때 호출된다. 직접 이 메서드를 호출하면 안 된다. 뷰의 일부분을 무효화하고 다시 그려지게 하려기 위해서는setNeedsDisplay 메서드를 호출할 수 있다. 뷰를 부분적으로 가리고 있던 다른 뷰를 이동, 제거하거나 hidden 프로퍼티를 수정한 경우에 뷰의 setNeedsDisplay를 호출한다. 뷰의 내용이 변경되면 draw메서드를 직접 호출하지 않고 setNeedsDisplay 메서드를 호출하여 뷰를 무효화한다. 이 메서드는 뷰의 내용이 변경되어 다음 사이클에 다시 그리도록 한다.
didSet 속성 감시자를 통해 setNeedsDisplay를 명시적으로 호출해 View 그리기를 요구할 수 있다.
class MyView: UIView {
var numberOfPoints = 0 {
didSet {
setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
switch numberOfPoints {
case 0:
return
case 1:
drawPoint(rect)
case 2:
drawLine(rect)
case 3:
drawTriangle(rect)
case 4:
drawRectangle(rect)
case 5:
drawPentagon(rect)
default:
drawEllipse(rect)
}
}
}
참고 :
https://daeun28.github.io/%EC%9D%B4%EB%A1%A0/post22/
http://monibu1548.github.io/2019/02/08/layout-cycle/
'iOS > iOS 정리' 카테고리의 다른 글
[iOS] Xcode 프로젝트 개념 (xcodeproj, xcworkspace의 차이) (3) | 2024.10.13 |
---|---|
[iOS] iOS Framework (0) | 2022.07.22 |
[iOS] invalidateIntrinsicContentSize() (0) | 2022.04.05 |
[iOS] UIView의 Layer란? (0) | 2022.04.01 |
[iOS] UIResponder (0) | 2022.03.30 |