🎯 코드베이스 UI
- 코드 베이스란 스토리보드 같은 인터페이스 빌더를 사용하지 않고, 코드 작성으로만 UI 구성을 하는 것
- 스토리보드에서 하던 뷰의 size, constraint 및 모든 속성들을 코드로 작성한다.
- 팀끼리 협업할 때, github에 코드를 올리고 서로 코드 리뷰를 하게 되는데, 스토리보드로 작성한 UI를 github에 올린 것보다, swift로 작성한 UI 코드를 github에 올린 것이 가독성이 더 좋음.
- 다만 스토리보드처럼 눈에 보이는 상태로 UI를 구성하는 것이 아니기 때문에, 코드 베이스로 UI를 작성하면 반드시 실행시켜서 확인해야 한다는 단점이 존재.
📚 스토리보드 삭제
🧐 스토리보드를 일절 사용하지 않고, 코드만으로 UI를 구성하기 위해 프로젝트에서 스토리보드를 완전히 삭제합니다.
1. Main이라는 이름의 스토리보드 삭제. Move to Trash로 삭제할 것
2. into.plist라는 파일에서 ctrl+F로 검색 → main 검색해서 Storyboard Name 항목 삭제
3. 프로젝트 파일에서 TARGETS 선택 후 → Build Settings로 이동 → ctrl+F로 main 검색 → UIKit Main Storyboard File Base Name 항목 삭제
4. 앱에게 맨 처음 시작할 뷰를 알려줘야 하므로 SceneDelegate.swift 파일에 다음과 같은 코드 작성
코드 및 설명
// SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// 윈도우. 앱에 반드시 한 개는 필요한 가장 근본이 되는 뷰. 이 위에 뷰가 쌓이기 시작.
var window: UIWindow?
// 앱을 시작할때 세팅해줄 코드를 작성하는 곳.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// UIWindow 객체 생성.
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
// window 에게 루트 뷰 지정.
window.rootViewController = ViewController()
// 이 메서드를 반드시 작성해줘야 윈도우가 활성화 됨.
window.makeKeyAndVisible()
self.window = window
}
🛠️ 코드베이스 UI 실습 - NSLayoutConstraint 사용
1. UI Label
import UIKit
class ViewController: UIViewController {
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
label.text = "안녕하세요"
label.textColor = .black
label.translatesAutoresizingMaskIntoConstraints = false // 오토레이아웃을 활성화 시키기 위해 작성하는 코드
view.addSubview(label)
NSLayoutConstraint.activate([
label.widthAnchor.constraint(equalToConstant: 80),
label.heightAnchor.constraint(equalToConstant: 40),
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
2. UI Button
import UIKit
class ViewController: UIViewController {
let button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
button.setTitle("Click", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .red
button.translatesAutoresizingMaskIntoConstraints = false
button.layer.cornerRadius = 10
view.addSubview(button)
NSLayoutConstraint.activate([
button.widthAnchor.constraint(equalToConstant: 120),
button.heightAnchor.constraint(equalToConstant: 60),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
3. UI ImageView
import UIKit
class ViewController: UIViewController {
let imageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
imageView.image = UIImage(named: "cat")
imageView.backgroundColor = .black
imageView.contentMode = .scaleAspectFit
imageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imageView)
NSLayoutConstraint.activate([
imageView.widthAnchor.constraint(equalToConstant: 300),
imageView.heightAnchor.constraint(equalToConstant: 300),
imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
🎯 SnapKit
💡 SnapKit 이란?
SnapKit 이란 코드베이스로 UI를 작성할 때, 조금 더 간결한 문법을 사용하도록 도와주는 서드파티 라이브러리.
NSLayoutConstraint을 사용할 때보다 편하게 코드를 작성할 수 있게 도와준다.
🧑🏻💻 현업에서 가장 많이 사용하는 필수 라이브러리 중 하나.
🛠️ 코드베이스 UI 실습 - SnapKit 사용
1. UI Label
import UIKit
import SnapKit
class ViewController: UIViewController {
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
label.text = "안녕하세요"
label.textColor = .black
view.addSubview(label)
label.snp.makeConstraints({ make in
make.width.equalTo(80)
make.height.equalTo(40)
// make.centerX.equalToSuperview()
// make.centerY.equalToSuperview()
make.center.equalToSuperview() // center X,Y를 한번에 작성 가능
})
}
}
2. UI Button
import UIKit
import SnapKit
class ViewController: UIViewController {
let button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
button.setTitle("Click", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .red
button.layer.cornerRadius = 10
view.addSubview(button)
button.snp.makeConstraints{
$0.width.equalTo(120)
$0.height.equalTo(60)
$0.center.equalToSuperview()
}
}
}
3. UI ImageView
import UIKit
import SnapKit
class ViewController: UIViewController {
let imageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
imageView.image = UIImage(named: "cat")
imageView.backgroundColor = .black
imageView.contentMode = .scaleAspectFit
view.addSubview(imageView)
imageView.snp.makeConstraints{
$0.width.height.equalTo(300)
$0.center.equalToSuperview()
}
}
}
4. UI Label, ImageView
import UIKit
import SnapKit
class ViewController: UIViewController {
let imageView = UIImageView()
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
imageView.image = UIImage(named: "cat")
imageView.backgroundColor = .black
imageView.contentMode = .scaleAspectFit
label.text = "고양이"
label.textColor = .black
label.font = UIFont.boldSystemFont(ofSize: 30)
[imageView, label]
.forEach{ view.addSubview($0)} // forEach문을 사용하여 불필요한 코드 작성을 줄임
imageView.snp.makeConstraints{
$0.width.height.equalTo(300)
$0.center.equalToSuperview()
}
label.snp.makeConstraints{
$0.centerX.equalToSuperview()
$0.top.equalTo(imageView.snp.bottom).offset(10)
}
}
}
5. UI ImageView, Label 2개씩
import UIKit
import SnapKit
class ViewController: UIViewController {
let imageView = UIImageView()
let label = UILabel()
let imageView2 = UIImageView()
let label2 = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
view.backgroundColor = .white
imageView.image = UIImage(named: "cat")
imageView.backgroundColor = .black
imageView.contentMode = .scaleAspectFit
label.text = "고양이"
label.textColor = .black
label.font = UIFont.boldSystemFont(ofSize: 30)
imageView2.image = UIImage(named: "dog")
imageView2.backgroundColor = .black
imageView2.contentMode = .scaleAspectFit
label2.text = "강아지"
label2.textColor = .black
label2.font = UIFont.boldSystemFont(ofSize: 30)
[imageView, label, imageView2, label2]
.forEach{ view.addSubview($0)} // forEach문을 사용하여 불필요한 코드 작성을 줄임
imageView.snp.makeConstraints {
$0.width.height.equalTo(160)
$0.leading.equalToSuperview().offset(16) // 리딩에서 바깥쪽으로 16만큼
$0.centerY.equalToSuperview()
}
label.snp.makeConstraints {
$0.centerX.equalTo(imageView.snp.centerX)
$0.top.equalTo(imageView.snp.bottom).offset(16)
}
imageView2.snp.makeConstraints {
$0.width.height.equalTo(160)
$0.trailing.equalToSuperview().inset(16) // 트레일링에서 안쪽으로 16만큼
$0.centerY.equalToSuperview()
}
label2.snp.makeConstraints {
$0.centerX.equalTo(imageView2.snp.centerX)
$0.top.equalTo(imageView2.snp.bottom).offset(16)
}
}
✓ TIL
현업에서는 스토리보드 UI 방식보다 코드베이스 UI를 주로 사용
NSLayoutConstraint 보다 SnapKit을 주로 사용
NSLayoutConstraint 사용시
translatesAutoresizingMaskIntoConstraints = false 를 작성하고
NSLayoutConstraint.activate([
imageView.widthAnchor.constraint(equalToConstant: 300)
])
형식으로 사용한다
SnapKit 사용시
translatesAutoresizingMaskIntoConstraints = false 를 작성할 필요가 없고
import SnapKit 작성 후
imageView.snp.makeConstraints{
$0.width.height.equalTo(300)
$0.center.equalToSuperview()
}
형태로 사용한다.
Button의 Action 코드를 구현할 때는
private func configureUI() {
view.backgroundColor = .white
button.setTitle("Click", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .red
button.layer.cornerRadius = 10
button.addTarget(self, action: #selector(buttonClicked), for: .touchDown)
view.addSubview(button)
button.snp.makeConstraints{
$0.width.equalTo(120)
$0.height.equalTo(60)
$0.center.equalToSuperview()
}
}
// #selector안에 넣기 위해서는 @objc
@objc
private func buttonClicked() {
print("버튼이 클릭되었음.")
}
2개 이상의 UI를 구현할 때는 forEach문을 사용하여 불필요한 코드 작성을 줄인다.
[imageView, label, imageView2, label2]
.forEach{ view.addSubview($0)} // forEach문을 사용하여 불필요한 코드 작성을 줄임
제약사항을 걸 때는
imageView.snp.makeConstraints {
$0.width.height.equalTo(160)
$0.leading.equalToSuperview().offset(16) // 리딩에서 바깥쪽으로 16만큼
$0.centerY.equalToSuperview()
}
imageView2.snp.makeConstraints {
$0.width.height.equalTo(160)
$0.trailing.equalToSuperview().inset(16) // 트레일링에서 안쪽으로 16만큼
$0.centerY.equalToSuperview()
}
- offset()과 inset()을 사용
- width와 height값이 같을때는 width.height.equalTo(160)처럼 한줄에 작성 가능
- euqalToSuperView는 제일 근본이 되는 View에 크기를 맞출 때 사용한다
- 왼쪽은 leading 오른쪽은 trailing
'스파르타 코딩 클럽 - iOS 스타터 6기 > 본 캠프' 카테고리의 다른 글
24. 스파르타 코딩 클럽 - 계산기 UI 만들어보기 (CodeBase) Lv1 ~ Lv5 (0) | 2025.03.31 |
---|---|
23. 스파르타 코딩 클럽 - iOS 앱 개발 입문 카운터 앱 만들기 (0) | 2025.03.27 |
21. 스파르타 코딩 클럽 - UIKit (1) | 2025.03.25 |
20. 스파르타 코딩 클럽 - 야구 게임 만들기 Lv2 ~ Lv6 (2) | 2025.03.21 |
19. 스파르타 코딩 클럽 - 야구 게임 만들기 Lv1 (2) | 2025.03.19 |