📌 아홉번째 프로젝트
명상 컨텐츠 리스트 앱을 만들어보자
1️⃣ Data 확인 및 SearchViewController 만들기
- 이전 프로젝트들과 마찬가지로 패캠에서 제공해준 데이터들을 사용
- "FocusViewController" 이름의 UIViewController을 만들어서, Main storyboard와 연결까지 완료
2️⃣ CollectionView AutoLayout 설정
- Description과 ContentView와의 관계에서 bottom을 30 이상이 되게 하면
이렇게 빨간색 에러점이 뜨게 되는데, 일단 이건 어쩔 수 없으니까 넘어간다.
3️⃣ UICollectionViewCell 만들기
- "FocusCell" 이름의 UICollectionViewCell을 만들어서 CollectionViewCell 연결 및 Collection Reusable Identifier을 설정
// FocusCell.swift
import UIKit
class FocusCell: UICollectionViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var thumbnailImageView: UIImageView!
func configure(_ item: Focus){
titleLabel.text = item.title
descriptionLabel.text = item.description
thumbnailImageView.image = UIImage(systemName: item.imageName)
}
}
4️⃣ UIViewController 정리
- Diffable Datasource, Snapshot, Compositional Layout
// FocusViewController.swift
import UIKit
class FocusViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
var items: [Focus] = Focus.list
typealias Item = Focus
enum Section {
case main
// Section이 많아지면 여기에 case를 더 추가하면 됨.
}
var datasource: UICollectionViewDiffableDataSource<Section, Item>!
override func viewDidLoad() {
super.viewDidLoad()
// (1) presentation -> DiffableDataSource
datasource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FocusCell", for: indexPath) as? FocusCell else {
return nil
}
cell.configure(item)
return cell
})
// (2) data -> Snapshot
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items, toSection: .main)
datasource.apply(snapshot)
// snapshot을 설정해주면, 이 정보말고 나머지는 가짜라고 설정된다.
// (3) laout -> Compositional layout
collectionView.collectionViewLayout = layout()
}
private func layout() -> UICollectionViewCompositionalLayout{
// .estimated(50) == 기본적으로 50인데 그저 추정값, 늘어남에 따라서 알아서 표현이 된다.
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
}
- Diffable Datasource를 쓰면,
이전의
let data = self.items[indexPath.item]
cell.configure(data)
↓
cell.configure(item)
으로 간단하게 바꿀 수 있다.
5️⃣ 좀 더 꾸미기
- 기본 tint값이 입혀진 image를 multicolor로 바꿔보기
// FocusCell.swift
func configure(_ item: Focus){
titleLabel.text = item.title
descriptionLabel.text = item.description
thumbnailImageView.image = UIImage(systemName: item.imageName)?.withRenderingMode(.alwaysOriginal)
}
→ withRenderingMode(.alwaysOriginal)
- 색과 Radius 설정
import UIKit
class FocusCell: UICollectionViewCell {
// ...
override func awakeFromNib() {
super.awakeFromNib()
contentView.backgroundColor = UIColor.systemIndigo
contentView.layer.cornerRadius = 10
}
// ...
}
- 좌우 패딩, group간의 spacing 주기
// FocusViewController.swift
import UIKit
class FocusViewController: UIViewController {
// ...
private func layout() -> UICollectionViewCompositionalLayout{
// ...
let section = NSCollectionLayoutSection(group: group)
// section에 좌우패딩주기
section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 20)
// group간의 spacing
section.interGroupSpacing = 10
// ...
return layout
}
}
6️⃣ 버튼 만들기
- Auto Layout
- 버튼 기능
// FocusViewController.swift
import UIKit
class FocusViewController: UIViewController {
@IBOutlet weak var refreshButton: UIButton!
var currated: Bool = false
// ...
override func viewDidLoad() {
// ...
// 삼항연산자를 통해 Button의 상태 설정
let title = currated ? "See All" : "See Recommendation"
refreshButton.setTitle(title, for: .normal )
}
// ...
@IBAction func refreshButtonTapped(_ sender: Any) {
currated.toggle()
self.items = currated ? Focus.recommendations : Focus.list
// collectionView가 업데이트 되어야 함
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items, toSection: .main)
datasource.apply(snapshot)
let title = currated ? "See All" : "See Recommendation"
refreshButton.setTitle(title, for: .normal)
}
}
🚀 구현 완료
7️⃣ Code Refactoring (DRY : Do not Repeat Yourself)
완성된 코드를 확인해보면
let title = currated ? "See All" : "See Recommendation"
이 코드가 두번 반복되고 있는 것을 볼 수 있다.
→ 함수로 처리하기!
func updateButtonTitle() {
let title = currated ? "See All" : "See Recommendation"
refreshButton.setTitle(title, for: .normal)
}
📌 정리,
- Presentation → Diffable DataSource
- Data → Snapshot
- Layout → Compositional Layout
- @IBAction 으로 Button 기능 구현하기
Reference
패스트캠퍼스 온라인 강의
'iOS > Toy project' 카테고리의 다른 글
[iOS : Toy Project] Apple Framework List (3) : Modal (0) | 2022.06.29 |
---|---|
[iOS : Toy Project] Spotify Paywall : CollectionView, Paging Control (0) | 2022.06.28 |
[iOS : Toy Project] Diffable DataSource, Compositional Layout을 이용해 프로젝트 개선하기 (0) | 2022.06.04 |
[iOS : Toy Project] NRC Onboarding (0) | 2022.05.31 |
[iOS : Toy Project] Insta Search View (2) (0) | 2022.05.29 |