Auto Layout이란 기존의 Frame-Based Layout과 다른 View들 간의 관계를 이용하여 View의 위치와 크기를 자동으로 결정하는 Layout System이며, 제약 조건(Constraints)을 이용해서 뷰의 위치를 지정하는 것이다. 쉽게 말하면, 두 뷰 사이의 관계를 제약 조건이라는 것을 이용해서 뷰의 크기와 위치를 지정하는 것이다.
오토 레이아웃은 여러 해상도를 지원하려고 나왔다. 아이폰의 크기가 다양해지면서 해상도도 달라졌는데, 다른 크기에서도 같은 화면을 똑같이 보여주기 위해 오토 레이아웃을 사용한다. 세로 보기 화면뿐만 아니라 가로 보기 화면까지도 지원한다. 아이폰SE 혹은 아이폰8 Plus에서도 같은 비율의 화면을 볼 수 있도록 오토 레이아웃을 사용하는 것이다. 만약 오토 레이아웃을 사용하지 않는다면, 아이폰 기종마다 스토리보드를 만들어야 한다. 이렇게 되면 스토리보드 파일이 많아진다. 앱을 실행할 때 아이폰 기종을 확인하고, 그에 맞는 스토리보드를 찾아 화면을 보여주는 번거로움도 생긴다. 오토 레이아웃을 사용하여 기종이 달라도 보여지는 화면이 똑같을 수 있도록 한다.
전통적으로 앱은 유저 인터페이스를 각 뷰의 프레임(frame)을 프로그래밍 방식으로 계산해 배치한다. 유저 인터페이스를 배치하려면 뷰 계층의 모든 뷰에 대한 크기와 위치를 계산해야 한다. 그리고 변경이 발생하면 영향을 받는 모든 뷰에 대해 프레임을 다시 계산한다.
뷰의 프레임을 프로그래밍 방식으로 정의하면 유연해진다. 어떤 변화가 생겨도 대응할 수 있기 때문이다. 그러나 모든 변경 사항을 직접 관리해야 하기 때문에 많은 노력이 필요하다. 설계부터 시작하여 디버그 및 유지 관리까지 많은 것을 관리해야 한다. 가장 효과적인 방법이지만 난이도도 많이 어려워진다.
이와 달리 오토 레이아웃은 일련의 제약 조건을 사용하여 유저 인터페이스를 정의한다. 제약 조건은 앞서 말한 것 처럼, 일반적으로 두 뷰 간의 관계를 나타낸다. 그런 다음 오토 레이아웃은 이러한 제약 조건을 기반으로 각 뷰의 크기와 위치를 계산한다.
화면에 배치하는 모습이 같기 때문에 프레임 방식을 사용해도 되고, 오토 레이아웃을 사용해도 된다. 둘 다 스위프트와 오브젝티브 C를 지원하기도 한다. 각각 장단점이 있지만 가장 많이 사용하는 방법이 오토 레이아웃이다. 빠르게 적용할 수 있고 많은 시간을 줄일 수 있기 때문이다.
![스크린샷 2021-11-24 오후 3.52.18](/Users/kimsian/Library/Application Support/typora-user-images/스크린샷 2021-11-24 오후 3.52.18.png)
순서대로 Stack, Align, Pin, Resolve Auto Layout Issues.
핀(Pin) 메뉴는 버튼 또는 레이블과 같은 UI 요소에 새로운 제약 조건들을 추가할 수 있다. 시계 방향으로 Top, Trailing, Bottom, Leading 제약 조건의 값을 입력할 수 있고, 화살표를 누르면 어떤 뷰와 관계를 가질 것인지 선택할 수 있다. 두 뷰와 핀 메뉴를 선택하면 같은 너비와 높이를 설정할 수 있다.
정렬(Align) 메뉴는 다른 뷰와의 가로, 세로 정렬과 같은 정렬 제약 조건들을 추가할 수 있다. 정렬하고 싶은 두 뷰를 선택하여 수직 정렬, 수평 정렬을 추가할 수 있다.
맨 오른쪽 메뉴인 오토 레이아웃 이슈 툴은 오토 레이아웃 관련된 이슈들을 해결하는 옵션들을 제공한다. 오토 레이아웃을 현재 설정된 상태로 재설정하는 옵션들이다. 상단은 선택된 뷰와 관련된 것이고, 하단은 모든 뷰와 관련된 것이다.
Align 옆에 있는 Stack 메뉴는 복잡한 제약 조건 없이 오토 레이아웃의 기능을 쉽게 뷰를 배치할 수 있도록 스택에 쌓아서 묶어주는 스택뷰를 생성한다. 하나의 묶음으로 만들 뷰들을 선택하여 Stack 메뉴를 선택하면 스택처럼 그룹으로 된다. 여기서 뷰 사이의 공간과 정렬들을 설정할 수 있다.
스토리보드에서만 제약 조건들을 설정할 수 있는 건 아니다. 프로그램 상에서도 제약 조건들을 설정할 수 있다. 스토리보드에서 뷰를 배치한 다음, 제약 조건들을 소스 파일과 연결해서 값을 지정할 수 있다. 주로 어떤 변화가 일어나면 제약 조건들을 다시 설정할 때, 프로그램 상에서 값을 다시 설정한다. 예를 들어, 데이터가 있을 땐 해당 뷰를 보여준다. 만약 데이터가 없으면 그 뷰가 사라지면서 그 뷰와 관련되어 있는 다른 뷰의 제약 조건들을 다시 설정하여 화면에 재배치하는 것이다.
func hideTag(_ hide: Bool) {
if hide {
self.labelTag1.isHidden = true
self.labelTag2.isHidden = true
self.constLabelTag1Top.constant = 0.0
self.constLabelTag1Height.constant = 0.0
} else {
self.labelTag1.isHidden = false
self.labelTag2.isHidden = false
self.constLabelTag1Top.constant = 15.0
self.constLabelTag1Trailing.constant = 5.0
self.constLabelTag1Height.constant = 20.0
}
}
위 소스에서 hide 값에 따라 레이블의 숨김을 설정하고 레이블의 제약 조건의 값을 재설정하는 메소드가 있다. 데이터가 있으면 숨김을 해제하고 제약 조건들의 값을 설정하지만, 데이터가 없으면 레이블을 숨기고 제약 조건들의 값을 0으로 설정한다.