코드베이스로 작업을 하기 위한 초기세팅을 먼저 정리해 볼게요!
Storyboard 삭제 세팅
1. Main.storyboard 스토리보드 파일 삭제 - > Move to Trash
메인 스토리보드를 제거해 주세요
2. Project TARGETS > Build Settings > Main Storyboard 삭제
프로젝트의 타겟으로 이동해서 메인 스토리보드도 삭제해 줍니다.
3. Info.plist > Storyboard Name > Main
위의 경로로 이동해서 스토리보드 키를 - 버튼 눌러서 삭제합니다.
4. SceneDelegate 수정하기⭐️⭐️
이제 어떤 뷰컨트롤러로 시작할지 지정해줘야 합니다!
씬델리게이트에서 scene() 메서드 안에 아래 코드로 내용을 수정해 줍니다.
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.rootViewController = ViewController() // 원하는 뷰컨트롤러로 변경해주기!
window?.makeKeyAndVisible()
5. VC 'backgroundColor' 변경하기
그대로 빌드하면 검정 화면이 나올 텐데 view색상이 없기 때문입니다.
시작 화면으로 지정한 뷰컨트롤러의 색상을 변경해서 빌드해 주면 됩니다.
이때 변경되지 않는다면 Xcode를 한번 껐다가 다시 실행해 주세요!! (저는 적용이 안 돼서 런치스크린이 문제인가까지 고민했는데 이런 이슈였습니다,,😂)
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
}
이렇게 했다면 코드베이스로 작업하기 위한 준비가 다 되었습니다.
CodeBase 연습하기
1. 코드로 오토레이아웃 잡기 - CodeBase UI
우선 코드베이스의 장단점은 다음과 같습니다.
<장점>
- 코드만 나와있기에 가볍고 Conflict 발생 가능성이 낮아진다. (충돌 파악 가능/ 협업에 유리)
- 스토리보드의 구현은 코드로도 가능하다.
- 더 다양한 UI적 표현이 가능하다.
<단점>
- 컴포넌트의 속성을 숙지해야한다.
- 화면이 만들어지는 과정에서 파악하기 힘들다.
- 코드가 왕창 길어진다.
- NSLayoutConstraint를 통해 AutoLayout을 설정해줘야 하는데 귀찮고 복잡하다 (SnapKit 라이브러리를 통해 극복 가능)
UI Component 추가하기
기존에 Outlet으로 연결한 것처럼 UI 컴포넌트를 초기화해서 넣어줍니다.
class ViewController: UIViewController {
// UI Component 추가하기
let nameLabel = UILabel()
let addButton = UIButton()
let myTableView = UITableView()
let stackView = UIStackView()
let button1 = UIButton()
let button2 = UIButton()
let button3 = UIButton()
addSubView 하기
View 안에 addSubView를 해주어야 합니다.
forEach문을 사용해서 코드를 간결화할 수도 있습니다.
// View안에 addSubView 해주어야함
view.addSubview(nameLabel) // --> 이런 식으로!
view.addSubview(addButton)
// forEach를 사용해서 코드 간결화
[nameLabel, addButton, myTableView].forEach {
view.addSubview($0)
}
우리가 스토리보드에서 뷰를 얹는 순서와 똑같기 때문에 addSubview를 해주는 순서가 중요할 수 있습니다!
ex) imageview 위에 label이 올라가는 경우
또한 stackview 에 요소를 넣을 때는 stackView에 요소를 넣을때는 addArrangedSubview를 사용해야합니다. 또한 이는 순서대로 스택뷰에 들어가게 되므로 순서가 중요합니다!
addSubView를 해주게 되면 계층 구조가 만들어져 부모-자식의 관계가 됩니다. 즉 button1의 `부모`는 stackView가 되기 때문에 button1의 `SuperView`는 stackView가 됩니다. SuperView는 코드로 오토레이아웃을 잡는데 많이 사용되므로 관계를 잘 파악해줘야합니다.
view.addSubview(stackView)
[button1, button2, button3].forEach { // --> 1, 2, 3 순서대로 들어감!
stackView.addArrangedSubview($0)
}
Cell 사용할 때 유의점
기존의 xib를 활용하는 방식이 아니기 때문에 awakeFromNib이 아닌 init을 오버라이드 해줘야 합니다.
또한 cell을 register 하는 과정에서 인스팩터 창에서 reuse identifier 설정해주는 것이 없기 때문에 타입 프로퍼티를 활용하면 좋습니다.
let myLabel = UILabel()
// static identifier 등록하기!
static let identifier = "NewTableViewCell"
//awakeFromNib 지우기
// init 추가해야함!!
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(myLabel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
테이블뷰에 셀을 등록할 때는 기존에 nib대신 cellClass가 포함된 regitster 메서드를 사용합니다.
// 테이블뷰 셀 등록할 때는 register에서 nib대신 CellClass!
myTableView.register(MyTableViewCell.self, forCellReuseIdentifier: MyTableViewCell.identifier)
Code로 Constraints 잡기
이제 컴포넌트를 등록하고 뷰에 넣는 방법을 알아봤으니 레이아웃을 잡아봅시다!
해줘야할 것은 두개만 기억합시다.
1. translatesAutoresizingMaskIntoConstraints = false 설정해주기
2. anchor (열심히) 연결해주기
❗️ translatesAutoresizingMaskIntoConstraints란 간단하게 기기에 맞춰 자동으로 크기를 조정해주는 기능입니다.
동적으로 뷰의 위치와 크기를 설정해줘야 한다면 이 기능을 꺼야합니다.
‘오토레이아웃을 코드로 하려면 꺼야하는 것’ 정도로 기억하면 됩니다.
또한 스토리보드에서 레이아웃을 잡던 대로 top, leading, trailing, height에 대한 anchor을 설정해줘야 합니다.
저는 safeArea에서 30씩 떨어지도록 아래와 같이 작성해서 확인했습니다.
nameLabel.translatesAutoresizingMaskIntoConstraints = false // 필수
// equalTo, equalToSystemSpacingBelow 보통 사용함
nameLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30).isActive = true
nameLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 30).isActive = true
nameLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 30).isActive = true
nameLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
이렇게 작성 후 빌드해보면 trailing이 예상과 다를 것입니다.
뷰의 방향에 대한 이해가 필요한데 뷰는 오른쪽, 아래 방향을 +방향으로 생각합니다. 즉 trailing에서 +30을 하게 되면 오른쪽으로 30, bottom에서 +30을 하게 되면 아래로 30만큼 멀어지게 되는것입니다.
그래서 bottom, trailing에서는 - 처리를 해야 이전에 스토리보드로 오토레이아웃을 잡는 것과 동일하게 잡힙니다!!
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30).isActive = true
nameLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 30).isActive = true
nameLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -30).isActive = true
nameLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
이렇게 수정해서 확인해보면 레이아웃이 잘 잡힌 것을 확인할 수 있습니다.
2. SnapKit 라이브러리 사용하기
사실 레이아웃 잡는 코드가 너무 길고 복잡하기 때문에 SnapKit을 사용하는게 일반적입니다.
바로 사용해봅시다!
라이브러리 Import하기
https://github.com/SnapKit/SnapKit
GitHub - SnapKit/SnapKit: A Swift Autolayout DSL for iOS & OS X
A Swift Autolayout DSL for iOS & OS X. Contribute to SnapKit/SnapKit development by creating an account on GitHub.
github.com
위의 링크 경로를 복사합니다!
프로젝트의 Package Dependencies에 복사한 url을 붙여넣고 AddPackage 버튼을 누릅니다.
❗️SnapKit-Dynamic의 타겟은 None으로 바꿔주세요! 안그러면 오류가 발생합니다.
왼쪽 파일에 라이브러리가 생겼다면 성공입니다!
SnapKit 사용해보기
기존 방식과 SnapKit을 사용했을 때 코드 비교입니다.
엄청 간단해진 코드를 확인할 수 있습니다!
equalToSuperview
SnapKit에서 자주 사용되는 방법입니다. 해당 뷰의 ‘부모 뷰’을 통해 제약조건을 설정합니다.
부모 뷰의 이름을 직접 적지 않아도 파악이 가능하기 때문에 더 깔끔하고 직관적인 코드를 작성할 수 있습니다.
코드 예시입니다. 클로저를 통한 축약 문법도 제공되고 여러 앵커를 한 번에 연결할 수도 있습니다!
nameLabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(30) // 위에서 30만큼 띔!
make.leading.equalToSuperview().offset(30)
make.trailing.equalToSuperview().offset(-30)
make.height.equalTo(50)
}
addButton.snp.makeConstraints {
$0.top.equalTo(nameLabel.snp.bottom).offset(20)
$0.centerX.equalToSuperview() // superView의 centerX랑 맞춤
}
// 여러 Anchor를 한 번에 연결하는 방법
nameLabel.snp.makeConstraints { // 여러 앵커를 한번에 연결
$0.top.leading.equalToSuperview().offset(30)
$0.trailing.bottom.equalToSuperview().offset(-30)
}
nameLabel.snp.makeConstraints { // (위, 아래) (리딩, 트레일링)을 한번에 표현하는 이름도 존재
$0.verticalEdges.equalToSuperview().offset(30) // 위 + 아래
$0.horizontalEdges.equalToSuperview().offset(30) // leading + trailing
}
Inset, Offset 이해하기
- 뷰의 방향을 그대로 활용하는 것이 Offset
- bottom, trailing등 -처리를 포함해서 안쪽을 향하도록 하는것이 Inset
// offset
myTableView.snp.makeConstraints {
$0.top.equalToSuperview().offset(10)
$0.leading.equalToSuperview().offset(10)
$0.trailing.bottom.equalToSuperview().offset(-10)
$0.bottom.equalToSuperview().offset(-10)
}
// inset
myTableView.snp.makeConstraints {
$0.top.equalToSuperview().inset(10)
$0.leading.equalToSuperview().inset(10)
$0.trailing.bottom.equalToSuperview().inset(10)
$0.bottom.equalToSuperview().inset(10)
}
// 축약
myTableView.snp.makeConstraints {
$0.top.leading.trailing.bottom.equalToSuperview().inset(10)
}
// edge를 이용한 축약
myTableView.snp.makeConstraints {
$0.edges.equalToSuperview().inset(10)
}
이렇게 스냅킷을 사용하는 방법을 공부해봤습니다.
이 공부를 토대로 코드베이스로 이번 과제를 열심히 해봐야겠어요!!
'Devlog👩🏻💻 > iOS' 카테고리의 다른 글
[iOS] 스냅킷 updateLayoutConstraints 크래시 (equalToSuperview) (2) | 2024.06.19 |
---|---|
[Error/Xcode] 시뮬레이터 SearchBar & TextField 키보드 오류 (4) | 2024.05.07 |
[iOS] Content Hugging Priority와 Content Compression Resistance Priority (4) | 2024.05.03 |
[iOS] 동기 vs 비동기, Serial vs Concurrent 이해하기 (8) | 2024.05.02 |
[iOS] CoreData 구성품 알아보기 (2) | 2024.04.22 |