- 씬이 변화되는 경우는 아래와 같다.
- 기기의 회전 : 기기를 세로 또는 가로로 회전하여 씬의 변화를 준다.
- 다른 화면 크기/배율의 기기에서 동작 : iPhone SE, iPhone X 등 화면의 크기와 배율이 다를 경우 씬의 변화가 생기게 된다.
- 동적인 씬 레이아웃 변화 : 세그먼티드 컨트롤처럼 다른 씬을 출력하는 경우 씬의 변화가 생기게 된다.
- 씬에 변화가 생겨도 제약조건을 주어서 씬의 변화에 대응하도록 할 수 있다.
- 기기를 회전 시에도 버튼이 출력되도록 할 수 있다.
- 제약 조건 작성
- 제약 조건은 씬의 구조에 따라서 컨텐츠 영역이 변경되게 되는데 이런 변화에 대응할 수 있게 새로운 프레임을 적용하도록 한다.
- 종류
- 레이아웃 가이드 : 씬의 구조에 따라서 컨텐츠 영역이 변경되는데 레이아웃을 참조하여 컨텐츠 영역을 결정한다. (Top / Bottom / Left / Right)
- 컨텐츠 마진 : 컨텐츠 배치의 기준선으로 컨텐츠가 화면에 어느 정도 떨어진 후에 배치가 되는지에 대한 여유 공간의 거리이다. (아래 빨간색 선이 컨텐츠 마진을 나타낸 선이다.)
- 컨텐츠의 위치잡기 : 4 방향의 거리, 부모 뷰와의 거리, 중앙 위치, 형제 뷰와의 거리를 통해서 컨텐츠의 위치를 잡게 된다.
- 제약 조건이 적용되는 시점은 뷰 컨트롤러의 레이아웃 적용 라이프 사이클에서 viewWillLayoutSubviews, viewDidLayoutSubviews 함수에서 적용된다.
- Storyboard에서 제약 조건 작성
- Storyboard에서는 아래 그림처럼 메뉴를 통해서 제약조건을 작성한다. : Update Frame, Stackview, Align, Add new Constraints, Resolve Auto Layout Issues
- 작성된 제약 조건 확인은 아래 그림에서 Constraints에서 확인할 수 있다.
- 코드로 제약 조건 작성
- 제약 조건 관련 클래스 NSLayoutContraint 로 제약 조건을 작성한다.
- init 메소드는 아래와 같다.
- NSLayoutAttribute 클래스 : top, bottom, leading, trailing, width, height 에 대한 제약 조건을 작성할 수 있다.
- NSLayoutRelation 클래스 : lessThanOrEqual, equal, greaterThanOrEqual 에 대한 제약 조건을 작성할 수 있다.
- 코드로 작성한 예시는 아래와 같다.제약 조건을 코드로 작성한 예시
let label = UILabel() self.view.addSubview(label)
// 오토 리사이즈로 인한 제약조건 생성 막기label.translatesAutoresizingMaskIntoConstraints = false// 왼쪽으로 20 포인트 여백
let leftConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leadingMargin, multiplier: 1.0, constant: 20)
// 씬 상단 레이아웃 가이드와 20포인트 여백
let topConstraint = NSLayoutConstraint(item: label, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 20)// 부모뷰에 제약조건 객체 추가 label.superview!.addConstraints([leftConstraint, topConstraint])
// 크기 제약조건
let widthConstraint = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 300)// 해당 뷰에 제약조건 추가 label.addConstraint(widthConstraint)
- 비주얼 포맷 언어 : 기호 언어에서 제약 조건 객체를 만들어준다.
- 사용 기호 : |, -
- 사용 방법
- 거리 지정 (H : 가로, V : 세로)비주얼 포맷 언어 거리 지정
// 가장 왼쪽과 버튼과의 거리 지정
|-[Button]
// 버튼을 가장 왼쪽부터 50만큼 떨어져 배치
|-50-[Button]
// 가장 위쪽과 버튼과의 거리 지정
V:|-[Button]
// 버튼을 가장 위쪽부터 70만큼 떨어져 배치
V:|-70-[Button] - 크기(괄호), 중요도(@ 기호)비주얼 포맷 언어로 크기 및 중요도 지정
// 버튼 크기를 100으로 지정
|-50-[Button(100)]
// 버튼 크기를 50으로 지정하고 중요도 지정
V:|-100-[Button(50@750)] - 뷰 간 거리비주얼 포맷 언어로 뷰 간 거리 지정
// ButtonA와 ButtonB 간 거리 지정
[ButtonA]-[ButtonB]
// ButtonA와 ButtonB 간 거리를 20만큼 떨어져 지정
[ButtonA]-20-[ButtonB]
// ButtonA와 ButtonB 간 거리를 상하로 20만큼 떨어져 지정
V:[ButtonA]-20-[ButtonB] - 비주얼 포맷 언어를 사용한 예시는 아래와 같다.비주얼 포맷 언어로 작성한 제약 조건
let label1 = UILabel() self.view.addSubview(label1) let label2 = UILabel() self.view.addSubview(label2)
// 오토 리사이즈로 인한 제약조건 생성 막기label1.translatesAutoresizingMaskIntoConstraints = false
label2.translatesAutoresizingMaskIntoConstraints = false
// 비주얼 포맷 언어에서 사용하는 뷰
let views = ["label1":label1, "label2":label2, "topGuide":self.topLayoutGuide]// 비주얼 포맷 언어로 제약조건 객체 생성
let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat:"|-20-[label1]-20-[label2]", options:[], metrics: nil, views: views)let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[topGuide]-100-[label1][label2]", options:[], metrics: nil, views: views)
// 부모뷰에 제약조건 추가label.superview!.addConstraints(horizontalConstraints) label.superview!.addConstraints(verticalConstraints