- 오토 레이아웃의 본질
- Input: Constraint들
- 연산: Constraint -> Equations -> (Linear Algebra)
- Output: 연관된 뷰들의 프레임
- Maintainable Layouts
- 뷰를 여러개로 쌓아야 한다면, 스택뷰를 쓰라
- 오토레이아웃 기반으로 만들어졌고, 방향 지정이 가능하다.
- 각 뷰의 비율 까지도 조정할 수 있다.
- Hidden할 때도 스무스하게 처리된다.(애니메이션도)
// iOS
UIView.animateWithDuration(1.0) {
self.subviewToHide.isHidden = !self.subViewToHide.isHidden
}
NSAnimationContext.runAnimationGroup({ context in
context.duration = 1.0
self.subviewToHide.animator().hidden = !self.subviewToHide.hidden
}, completionHandler: nil)
- stackView의 하위 뷰이지만 stack되지 않는 뷰는 그냥 addSubView 해주면 된다.
- IB에서의 스택뷰
- 빌드가 편하다
- 유지보수가 편하다
- 합성이 가능하다.
- 단순히 레이아웃이기 때문에 렌더링하는 비용이 적게 든다.
- Changing Constraints
- constraint 선언 -> 레이아웃 엔진 -> 레이아웃
- 기존 컨셉은 constraint를 add/remove하는 것이였는데, 그러지 말라
- 대신activate/deactivate해라.
- Constraint가 뷰를 직접 찾는다.
- 효율적으로 constarints를 추가할 수 있따.
- 모든 뷰를 가지고 있을 필요가 없다.
- 염두할 것
- 절대로 self.view.constraint를 한꺼번에 deactivate하지 마라.
- 개발자가 직접 만들지 않은 것도 포함되어 있다.
- 대신 바꿀 constraint에 대한 참조를 따로 가지고 있다가 이걸로 다루라.
- constraint 변경은 애니매이션이 가능하다. 애니매이션 할 수 있으면 하라
- View Sizing
- Constraint이외에도 추가적으로 쓸 수 있는 정보가 있다면 좀 더 좋은 결과를 낼 수 있다.
- intrinsic context size: 라벨, 이미지 뷰 등은 본연의 사이즈를 가지고 있다.
- 이 정보를 받아서 엔진이 크기 constraint를 만들어준다.
- 다만 크기가 유지될 것 이란 보장은 하지 못한다.
- 뷰 크기를 결정할 때
- constraint를 우선 사용하라.
- intrinsicContentSize를 오버라이드 해야 될 때는
- constraint에서 size 정보를 구할 수 없을 때
- 커스텀 드로잉을 할 때(꼭 그런 것은 아님)
- 대신 오버라이드를 하면 직접 intrinsicContentSize를 invalidate할 책임이 있다.
- Self-Sizing Table View Cells
- Self-Sizing Cell은 constraint를 기반으로 사이즈를 구한다.
- width는 이미 주어져 있으니 height만 신경 쓰면 된다. -> height에 대한 constraint가 반드시 주어져야 한다. -> 비율로 지정해 주는 것이 좋다.
- Priorities
- ambiguity 문제가 있을 수 있다.
- constraint 수가 부족하거나
- 우선순위가 같은 Constraint가 충돌할 때
- 우선순위는 1~1000의 값을 가진다.
- 1000은 required(필수)
- default High: 750, default low: 250
- 일부 우선순위 값음 시스템에서 이미 사용하고 있다.
- window 에서 대략 500 정도의 값 사용
- 1000으로 설정하면 문제가 생겼을 때 unsatisfiable constraint 문제가 생길 수 있다.
- content자체의 제약
- content hugging: 컨텐츠보다 뷰가 줄어들려는 것 기본이 250(low)
- content compression resistance: 컨텐츠보다 뷰가 늘어나려는 것. 기본이 750(high)
- Alignment: 레이아웃 엔진의 마지막 입력
- baseline Alignment: 텍스트가 들어간 뷰를 정렬할 때는 top, bottom 보다 좋다.
- 텍스트가 포함 된 뷰의 변화에 따른 대응을 하기 좋다.
- Leading / Trailing: 언어에 따른 방향 변화에 대응하기 좋다. Left / Right보다 좋다.
- Alignment Rect: 레이아웃을 위해 사용
- 기본적으로는 프레임과 동일하다(not always)
- 핵심 컨텐츠만 포함한다.
- 뷰가 트랜스폼 되어도 변하지 않는다.
- 필요하면 alignmentRectInsets를 오버라이드 할 수 있다.
- 디버깅하는 법
- IB에서는 Show Alignment Rectangle을 디버그 메뉴에서 활성화 시켜라
- alignmentRectForFrame: 메소드를 써도 된다.
- Part2에서 보강할 예정
- 여기까지 해서, 레이아웃 엔진의 입력은
- 뷰 사이의 constraint
- 뷰의 크기 constraint,
- intrinsicContentSize
- Constraint들의 우선순위
- Content에 의해 자연적으로 생기는 Constraint들의 우선순위(Hugging, Compression Resistance)
- alignment
- Baseline alignment
- Vertical alignment
- Horizontal alignment
- Alignment rect insets
- 레이아웃 엔진은 alignment rects를 만들어서 배치하고, 이를 통해서 실제 레이아웃을 만들어 낸다
Part2
- The Layout Cycle
- App RunLoop -> Constraint Change -> Deferred Layout Pass -> App RunLoop
- Constraint Change
- activating / deactivating
- Constant / Priority 변경
- 뷰 추가 및 제거
- Constraint가 바뀌면
- 이후 재계산 된 뷰를 재 배치함
- legacy layout과의 소통
- Constraint 만들기
- Negative Space에 대한 Constraint
- 디버깅하기
- Ambiguity 해결