Open womyo opened 1 week ago
제약 조건의 우선순위는 1부터 1000 사이의 값을 가지며, 높은 값일수록 더 높은 우선순위를 가짐
// 속성에 따른 기본 우선순위 레벨 UILayoutPriority.required = 1000 // 반드시 만족해야 하는 제약조건 UILayoutPriority.defaultHigh = 750 // 높은 우선순위 UILayoutPriority.defaultLow = 250 // 낮은 우선순위 UILayoutPriority.fittingSizeLevel = 50 // 컨텐츠 맞춤 우선순위
우선순위 동작 특징
Intrinsic Content Size: 뷰가 자신의 컨텐츠를 기반으로 자연스럽게 가지는 크기 ex) UILabel의 텍스트에 따라 자연스러운 크기를 가지게 되는 그런 느낌?
// 각 UI 요소별 Intrinsic Content Size 특성 let label = UILabel() // width, height 모두 가짐 let button = UIButton() // width, height 모두 가짐 let textField = UITextField() // height만 가짐 let imageView = UIImageView() // 이미지가 있을 때만 width, height 가짐
활용법
Content Hugging과 Compression Resistance
- Content Hugging: 컨텐츠를 감싸안으려는 힘 뷰가 자신의 컨텐츠보다 커지는 것을 저항하는 정도, 우선순위가 높을수록 컨텐츠 크기를 유지하려 함
- Compression Resistance: 컨텐츠가 압축되지 않으려는 힘 뷰가 자신의 컨텐츠보다 작아지는 것을 저항하는 정도, 우선순위가 높을수록 컨텐츠가 잘리지 않음
// 두 레이블이 있을 때 왼쪽 레이블은 크기를 유지하고 // 오른쪽 레이블이 남는 공간을 차지하게 하고 싶을 때 leftLabel.setContentHugging(.defaultHigh, for: .horizontal) rightLabel.setContentHugging(.defaultLow, for: .horizontal)
주의할 점
// MARK: 모호성 진단 방법
// 뷰의 모호성 확인
view.hasAmbiguousLayout
// 모호한 레이아웃 시각화 (디버깅용) UIView.exerciseAmbiguityInLayout()
// 현재 레이아웃 로그 출력 view.constraintsAffectingLayout(for: .horizontal).forEach { print($0) }
// MARK: 일반적인 해결 방법 // 1. 누락된 제약조건 추가 // 2. 우선순위 조정 // 3. Content Hugging/Compression Resistance 조정
## 2. Unsatisfiable Constraints (충돌하는 제약조건)
- 동시에 만족할 수 없는 제약조건들이 있을 때 발생
- Required(1000) 우선순위의 제약조건들이 충돌할 때 발생
```Swift
class ConflictingView: UIView {
func setupConflictingConstraints() {
let redView = UIView()
addSubview(redView)
redView.translatesAutoresizingMaskIntoConstraints = false
// 충돌하는 제약조건
NSLayoutConstraint.activate([
redView.widthAnchor.constraint(equalToConstant: 100),
redView.widthAnchor.constraint(equalToConstant: 200) // 여기서 충돌
])
}
}
// 해결 방법 1: 우선순위 조정
func resolveWithPriority() {
let constraint1 = redView.widthAnchor.constraint(equalToConstant: 100)
constraint1.priority = .defaultHigh // 750
let constraint2 = redView.widthAnchor.constraint(equalToConstant: 200)
constraint2.priority = .defaultLow // 250
NSLayoutConstraint.activate([constraint1, constraint2])
}
// 해결 방법 2: 불필요한 제약조건 제거
func resolveByRemoving() {
NSLayoutConstraint.activate([
redView.widthAnchor.constraint(equalToConstant: 100)
// 충돌하는 제약조건 제거
])
}
필요한 제약조건 추가
- Content Hugging/Compression Resistance 조정
- 기본값 설정
- 우선순위 조정
Unsatisfiable Constraints 해결:
충돌하는 제약조건 식별
- 우선순위 조정
- 불필요한 제약조건 제거
- 제약조건 로직 재검토
Auto Layout을 사용하는 이유와 장점은 무엇인가요? 제약조건을 통해 뷰의 사이즈와 위치를 동적으로 조절하기 위함. 기기나 화면의 크기, 방향이 바뀌어도 일관된 인터페이스 유지 가능하며, 레이아웃의 수정이 쉬워짐
제약 조건(Constraints)의 우선순위(Priority)는 어떻게 동작하나요? 어떤 제약조건을 우선할 건지 1~1000까지 우선순위를 설정할 수 있음. 숫자가 높을 수록 우선순위가 높고, 제약 조건이 서로 충돌하는 경우 낮은 우선순위의 제약 조건은 무시됨. 1000은 필수조건, 750 defaultHigh, 500 defaultMedium, 250 defaultLow 등 미리 지정된 값이 있음
Intrinsic Content Size란 무엇이며, 어떻게 활용되나요? 뷰 자체의 속성을 고려한 뷰의 고유한 사이즈. 기본적인 컨텐츠의 사이즈가 정해져있어서 constraint를 따로 주지 않아도 문제가 생기지 않는 경우가 있음. 예를 들어 커스텀 버튼의 경우 나중에 폰트를 바꿔줘야 할 때 width, height을 직접 지정해두는 것보다 intrinsicContentSize를 오버라이드해서 지정해두는 것이 작업의 유연성을 높임. (플젝할 때, 셀의 높이를 동적으로 지정해줘야했는데 셀 내부의 스택뷰의 높이는 고정해줘야 해서 레이아웃 경고가 생기고 레이아웃이 깨지는 경우가 있었음. 이때 intrinsicContentSize를 정해줘서 뷰의 크기를 명확하게 계산할 수 있게 하여 해결함. )
Ambiguous Layout과 Unsatisfiable Constraints는 무엇이며, 어떻게 해결하나요?
Ambiguous Layout: 뷰의 위치나 크기가 모호하여 정확히 결정되지 않은 상태 추가적인 제약이 더 필요한 경우 → 어떤 뷰가 모호한지 파악하고 해당 뷰의 위치와 사이즈 제약조건을 추가하기 동일한 우선순위의 선택적인 제약조건이 충돌했는데 시스템이 어떤 제약조건을 깨야하는지 모르는 경우 → 충돌하는 제약조건의 우선순위를 조정해주어, 시스템이 더 낮은 우선순위의 제약조건을 깨도록 하기
Unsatisfiable Constraints: 동시에 모두 만족될 수 없는 두 개 이상의 제약조건이 충돌했는데 시스템이 유효한 해결책을 찾을 수 없는 경우 발생 이런 경우 시스템은 유효한 레이아웃이 될 때까지 하나씩 제약조건을 깨고 확인하는 과정을 반복하고 콘솔에 로그를 띄워줌. 언제 발생하고 무슨 제약조건 때문에 발생하는지 리스트도 제공해줌. → 해당 제약조건들을 제거하거나 optional한 제약조건으로 변경하기
뷰의 frame 좌표를 직접 지정해주는 것이 아니라 상대적으로 제약조건(Constraints)을 줌 뷰의 위치와 크기를 동적으로 지정. 다양한 화면 크기, 회전 지원
1 ~ 1000의 우선순위 값. 높은게 우선
UI 요소가 본래의 콘텐츠에 따라 자연스럽게 차지하는 크기. UILabel의 경우 레이블에 설정된 텍스트와 글꼴 크기에 따라 너비와 높이가 자동으로 결정
앱에서 표시되는 콘텐츠 변경 국제화를 지원 Dynamic Type(iOS)을 지원
제약 조건의 우선 순위 수준이 macOS에서 필수 또는 iOS에서 UILayoutPriorityRequired보다 낮으면 선택 사항입니다. 우선순위가 높은 제약 조건이 우선순위가 낮은 제약 조건보다 먼저 충족되지만, 선택적 제약 조건의 충족은 전부 또는 전무가 아닙니다. 제약 조건 a == b가 선택 사항인 경우, 제약 조건 기반 레이아웃 시스템은 abs(a-b)를 최소화하려고 시도합니다.
뷰 자체의 속성만 고려한 뷰의 자연스러운 크기 UIButton의 경우 텍스트, 이미지, 패딩에 따라 크기가 달라짐.
제약 시스템에 두 개 이상의 유효한 솔루션이 있을 때 발생
Ambiguous Layout은 Unsatisfiable 보다 오류를 식별하기 어려운 경우가 많음 view.hasAmbiguousLayout을 호출하여 true/false를 확인 해당 값이 true면 Ambiguous Layout임
현재 제약 조건 집합에 대한 유효한 솔루션을 찾을 수 없을 때 발생
기본적으로 새 뷰의 속성은 translatesAutoresizingMaskIntoConstraints으로 설정 캔버스에서 뷰에 제약 조건을 그리기 시작하면 Interface Builder가 자동으로 이 속성을 로 설정 그러나 프로그래밍 방식으로 뷰를 만들고 레이아웃하는 경우 사용자 정의 제약 조건을 추가하기 전에 속성을 False로 설정
기기의 크기, 방향 상관없이 인터페이스를 동적으로 배치하고 크기를조정할 수 있게 함. 일.관.성
1) 동적 레이아웃 지원 2) 유지 보수 편리성 3) 다양한 기기 대응 가능
각 제약에는 우선 순위 값 (0~1000)이 설정됨.
1000: 필수 제약(무.족.권 지켜야함)
999이하: 선택적 제약 (충돌시 무시될수있음) -> 우선순위가 낮은 제약은 충돌이 발생하면 제거되어 더 높은 우선순위를 가진제약을 따름
예) UIView를 왼쪽 10고정(Priority: 1000), 오른쪽 10고정 (Priority: 750)으로 설정하면 화면이 작아질 경우 오른족 제약이 먼저 무시됨.
5-1) Ambiguous Layout
5-2) Unsatisfiable Constraints
제약조건 우선순위 Required (1000): 무조건 지켜야 함(필수) 이하 낮을수록 우선순위 낮음 // High (750): 가능하면 지켜야 함 // Low (250): 여유가 있을 때 지킴
Intrinsic Content Size:
뷰가 자신의 콘텐츠를 표시하는데 필요한 자연스러운 크기 예: Label의 텍스트 길이, ImageView의 이미지 크기
Ambiguous: 레이아웃이 모호한 경우 (제약 부족) Unsatisfiable: 제약조건이 충돌하는 경우
다양한 기기와 화면 크기에서 일관된 사용자 인터페이스를 제공하기 위해 사용.
제약 조건의 우선순위는 Auto Layout 시스템이 여러 제약 조건 간의 충돌을 해결하는 방법을 결정.
우선순위는 1부터 1000까지의 값을 가지며, 높은 값일수록 더 중요한 제약 조건을 나타냄.
예를 들어, 버튼의 너비에 대해 두 개의 제약 조건이 있다고 가정하면,
이 경우, 우선순위가 더 높은 제약 조건 A가 적용되어 버튼의 너비는 100 이상이 됨.
Intrinsic Content Size는 뷰의 콘텐츠에 따라 자동으로 결정되는 기본 크기를 의미.
꼬리질문