-
[iOS] 객체 레이아웃, Code base UI 구현카테고리 없음 2025. 1. 13. 13:52
UI 그리는 법
- storyboard(IB)
- xib
- 코드
UI를 그리는 방법은 총 3가지가 있다. 이번엔 코드베이스 중점으로 보게 될텐데
코드 베이스와 스토리보드의 큰 차이점은?- 스토리보드에서 다뤘던 뷰 객체, 뷰 컨트롤러, 시작점, info.plist ⇒ 전부 코드로 변화해서 시작해야한다.
- 코드베이스여도, Launch Screen은 두고 하는 편
- 파일이 누락됐다고 생각할 수도 있기 때문에 심사가 멈출 수 있다.
- 팀 협업, 유지보수에 코드 베이스가 더 유리하게 작용한다.
객체 레이아웃
우선 코드로 구성하기 전 객체 레이아웃에 대해 살펴본다.
뷰 객체들을 배치하기 위해선 레이아웃이 항상! 필요하다.
스토리보드에서 자주 사용하던 AutoLayout은, Frame based layout부터 여러 기기를 대응하기 위해 더 나아진 레이아웃이라고 생각하면 된다.총 4가지의 레이아웃을 갖고 있고, 점차 나아지는 레이아웃이라고 생각해주면 된다.
(*Adative layout은 아직 다루지 않아 설명에선 제외했다.)- Frame based layout
- Auto ResizingMask
- Auto layout (핸드폰 기기에 맞춰 다양하게)
- Adaptive layout (아이패드, 워치 등 다양한 기기)
Frame based layout
왼쪽과 같이, 왼쪽 상단을 기준으로 화면을 좌표로 수치화 해, 상수를 기반으로 frame을 정하는 것을 의미한다.
문제는 이렇게 되면 여러 기기에 대응하기가 어려워진다.
각 기기별 width, height에 따라 숫자가 달라지기 때문에 나누기도 쉽지 않고,
원하는 대로 안나올 가능성이 높다.AutoResizingMask
Auto layout은 많이 들었을텐데, 그 전에 나온게 Autoresizing Mask 이라는 동적인 레이아웃을 구성할 수 있는 Apple이 도입한 예전 방식의 기능이다.
기기별 사이즈로 인해 슈퍼뷰의 경계가 변경될 때, 서브뷰의 크기를 조정하는 방법을 결정하는 정수형 비트마스크이다.- Autoresizing Mask로 결정된 레이아웃은 Auto layout contstraint로 변환되기 때문에, 바뀐 이후 코드로 제약 조건을 수정하는 것이 불가능하다.
즉, 뷰에서 설정한 Autoresizing Mask 값은 Auto Layout constraint로 자동으로 변환되는 것이다. - 그러므로, Autoresizing & Auto Layout을 동시에 적용해 수정하면 레이아웃 충돌이 발생할 수 있다. 충돌을 방지하기 위해 코드로 Auto Layout 방식을 사용할 때는 반드시 translatesAutoresizingMaskIntoConstraints 속성을 false로 설정해줘야한다.
AutoResizingMask 사용 예시
- Autoresizing Mask는 gui 상에서 아래와 같이 constraint 화살표를 선택할 수 있고, 코드로도 설정 가능하다.
코드sampleSubview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
- bottom, trailing 기준으로 AutoResizingMask를 설정한 상황에서, 기기별 경계값을 바꾸기 위해 아이폰 16 → SE로 바꿔주었다.
- 설정한 bottom, trailing의 여백을 기준으로 기기별로 대응하는 것을 확인할 수 있다.
좌 - 아이폰 16, 우 - 아이폰 SE - 슈퍼뷰를 기준으로 뷰의 크기를 늘리거나 줄이는 것인데, 이 기준을 설정한 constraint를 기준으로 얼마만큼 늘릴지 말지를 결정한다.
- 아래 사진으로 예시를 들면, 현재 화살표를 보면 bottom, trailing 에 제약 조건을 준다.
Auto layout
모든 뷰에 크기, 위치를 동적으로 계산하도록 제약 조건을 걸어준다.
constraint 값으로 슈퍼뷰, 다른 뷰 객체들에 관계나 여백을 기준으로 조건을 걸어주면, 기기에 따라 변하는 것에 동적으로 반응하는 레이아웃을 만들 수 있다.우리가 자주 사용하는 아래와 같은 constraint 들이 전부 Auto Layout에 해당한다.
스토리보드에서 위처럼 잡던 방식을, 코드로 바꾸면 NSLayoutConstraint 이다.
Code based UI
객체 선언 및 등록
스토리보드로 구성할 때는 아래와 같이 구성했다.
1. 스토리보드에서 객체 얹히기 2. 객체 레이아웃 잡기 3. 아웃렛 연결하기 4. 객체 속성 코드로 조절하기
코드베이스로 위를 바꾼다면 크게 이런 순서이다.
뷰 객체 선언 + addSubView(뷰 계층 구조에 등록) -> 객체 레이아웃 설정(뷰 크기도 설정 가능) -> 객체 속성 코드로 조절
- addSubView 다음에 꼭 속성을 조절해야한다. (안그럼 런타임 에러 발생)
- addSubView의 순서에 따라 겹쳐지는 뷰가 안보일 수 있다. (순서도 중요)
- AutoResizing mask 부분 false로 바꿔주는 걸 잊지말자!(우리는 autolayout을 사용할 것이기 때문에)
class ViewController: UIViewController { // 1. 객체 선언 let emailTextField = UITextField() override func viewDidLoad() { super.viewDidLoad() // 기본적으로 AutoResizing mask가 깔려있기 때문에 없애줘야한다. emailTextField.translatesAutoresizingMaskIntoConstraints = false // 2. addSubView 로 뷰 추가 view.addSubview(emailTextField) // 3. 객체 속성 코드로 조절 emailTextField.backgroundColor = .gray } }
객체 레이아웃 설정 & 실행
- 객체 레이아웃을 NSLayoutConstraint 으로 설정하고, 그 constraint를 실행시키는 방법에는 총 3가지가 있다.
- isActive, addConstraint, activate
- isActive: NSLayoutConstraint에 프로퍼티를 이용해 실행시키는 방법
NSLayoutConstraint(item: emailTextField, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 50).isActive = true
2. addConstraint: 한번에 배열로 전달하는 방법
let leading = NSLayoutConstraint(item: emailTextField, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 40) let trailig = NSLayoutConstraint(item: emailTextField, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: -40) let height = NSLayoutConstraint(item: emailTextField, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 50) view.addConstraints([leading, trailig, height])
3. activate: NSLayoutConstraint.activate의 배열에 제약조건을 넣는 방법
func autoLayoutAnchor() { NSLayoutConstraint.activate([ nameTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor), nameTextField.widthAnchor.constraint(equalToConstant: 300), nameTextField.heightAnchor.constraint(equalToConstant: 50), nameTextField.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) }
보통 3번이 간결해서 많이 사용하는 것 같다.
아무래도 스토리보드로 짜던 constraint가 코드베이스가 되니 너무 코드가 길어지게 되는데…
이를 보완하고자 많은 기업에서도 SnapKit 프레임워크를 사용한다.
글이 너무 길어지기에… 다음 글에선 SnapKit 사용법 작성을 해보려 한다.