let label = UILabel()
label.frame = CGRect(x: 20, y: 100, width: 200, height: 40)
frame 설정을 통해 직접 x, y 위치와 width, height를 지정해서 뷰를 배치하는 방법frame vs boundsSuperview (부모)
+-----------------------------+
| |
| +-----------------+ |
| | Subview | |
| | frame: (50,100)| |
| | bounds: (0,0) | |
| +-----------------+ |
| |
+-----------------------------+
| 개념 | 의미 | 기준 | 영향 |
|---|---|---|---|
frame | 부모 기준 뷰의 위치와 크기 | 부모 뷰 | 위치 이동/크기 조절 |
bounds | 자기 내부 기준 크기와 좌표계 | 자기 자신 | 내부 콘텐츠 위치/스케일 |
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
label.widthAnchor.constraint(equalToConstant: 200),
label.heightAnchor.constraint(equalToConstant: 40)
])
💡 다양한 Attributes
leading,trailing,left,right,top,bottom,centerX,centerY,center,width,height...leading: 왼쪽 ❌, Text가 시작되는 시점trailing: 오른쪽 ❌, Text가 끝나는 시점- 🚨 대부분의 언어에서는 문제 없지만, 아랍권은 글을 쓰는 방향이 반대
| 항목 | Frame-Based Layout | Auto Layout |
|---|---|---|
| 코드 작성 | 단순 | 복잡 |
| 유연성 | 낮음 | 높음 |
| 회전 대응 | ❌ 수동 계산 | ✅ 자동 대응 |
| 화면 크기 대응 | ❌ 불편 | ✅ 유연 |
| 추천 상황 | 고정된 간단 UI | 반응형 UI, 여러 디바이스 |
myView.translatesAutoresizingMaskIntoConstraints = false
translatesAutoresizingMaskIntoConstraints = true일 경우, Autolayout을 결정짓기 위해 설정한 Constraints가 AutoresizingMask와 충돌하기 때문에 동작하지 않음UILabel, UIButton, UIImageView 등은 내부 콘텐츠 크기에 따라 자동 크기 결정 가능🚨 예외
UIView,UIImageView(frame 기반)등은 intrinsic size 없음 → 반드시 constraint로 크기를 설정해야 함
| 키워드 | 역할 | 핵심 포인트 |
|---|---|---|
translatesAutoresizingMaskIntoConstraints | Frame → Auto Layout 전환 | 반드시 false로 설정해야 충돌 방지 |
safeAreaLayoutGuide | 노치/홈바 피해서 UI 배치 | iPhone X 이상에서 안정적인 UI 구현 |
intrinsicContentSize | 콘텐츠 기반 자동 크기 계산 | UILabel/UIButton 등에 적용됨 |
Auto Layout은 제약 조건이 너무 많거나, 너무 적거나, 모호하면 충돌(conflict)이 발생한다. 그래서 Auto Layout은 “어떤 조건을 더 중요하게 생각할지(우선순위)”를 기준으로 가장 적절한 해결안을 스스로 찾아내려고 한다.
💡 우선순위(priority) 숫자
- 숫자가 클수록 더 중요!
- 무조건 지켜야 하는 조건
.required: 1000- 가능한 지키되, 필요하면 깨질 수 있는 조건
.defaultHight: 750.defaultLow: 250.fittingSizeLevel: 50
label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
label.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
label1, label2를 수평으로 배치import UIKit
class ViewController: UIViewController {
let label1 = UILabel()
let label2 = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
// 기본 설정
label1.text = "첫 번째 레이블"
label2.text = "두 번째 레이블이 더 길어요!"
label1.backgroundColor = .systemYellow
label2.backgroundColor = .systemGreen
label1.numberOfLines = 1
label2.numberOfLines = 1
// 오토레이아웃 활성화
label1.translatesAutoresizingMaskIntoConstraints = false
label2.translatesAutoresizingMaskIntoConstraints = false
// 뷰에 추가
view.addSubview(label1)
view.addSubview(label2)
// Auto Layout Constraints
NSLayoutConstraint.activate([
label1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
label2.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
label1.trailingAnchor.constraint(equalTo: label2.leadingAnchor, constant: -10),
label1.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100),
label2.topAnchor.constraint(equalTo: label1.topAnchor),
])
// Content Hugging & Compression Resistance 설정
label1.setContentHuggingPriority(.defaultLow, for: .horizontal)
label2.setContentHuggingPriority(.defaultHigh, for: .horizontal)
label1.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
label2.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
}
}
label1은 Hugging / Compression Resistance이 약해서 → 눌림label2는 Hugging / Compression Resistance이 강해서 → 모양 유지label1이 크기를 양보하고 줄어드는 걸 확인할 수 있다!| 개념 | 설명 | 값이 클수록 |
|---|---|---|
| Priority | constraint 우선순위 | 꼭 지켜야 함 |
| Hugging Priority | 넓게 퍼지는 걸 방지("나 더 커지기 싫어!") | 더 작게 유지하려 함 |
| Compression Resistance | 작아지는 걸 방지("나 눌리기 싫어!") | 더 크게 유지하려 함 |