티스토리 뷰
UICollectionView를 Programmatically 하게 사용하는 방법이다.
원래 cellForItemAt에서 cell의 요소에 접근하는 방식을 cell.titleLabel.text = "" 이런 식으로 사용했는데
이번엔 다른 방법으로 접근해보고자 한다.
먼저 Collection View Cell은 다음과 같이 만들었다.
MyCollectionViewCell.swift
//
// MyCollectionViewCell.swift
//
import Foundation
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
static let identifier = "MyCollectionViewCell"
private let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.textAlignment = .center
label.font = .systemFont(ofSize: 25, weight: .semibold)
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
// Congifure Label
contentView.addSubview(label)
contentView.layer.cornerRadius = 6
contentView.layer.borderWidth = 1.5
contentView.layer.borderColor = UIColor.quaternaryLabel.cgColor
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
label.frame = contentView.bounds // label의 프레임을 cell의 바운드와 같게 조정
}
}
다음으로 ViewController에 CollectionView를 추가해주자.
ViewController.swift
//
// ViewController.swift
import UIKit
import SnapKit
class ViewController: UIViewController {
let cellMultiplier: CGFloat = 0.5
// Create UICollectionView
private let collectionView: UICollectionView = {
// Configure Layout
var layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .black
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
configureLayout()
configureCollectionView()
}
// SetUp AutoLayout with SnapKit
func configureLayout() {
// Add SubView
view.addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.width.equalToSuperview()
make.height.equalTo((view.frame.size.height / 5 ) * 3)
make.top.leading.equalTo(view.safeAreaLayoutGuide)
}
}
func configureCollectionView() {
// Attach CollectionView Delegate & DataSource
collectionView.delegate = self
collectionView.dataSource = self
// Regist Cell
collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.identifier)
}
}
extension ViewController: UICollectionViewDelegate {
}
extension ViewController: UICollectionViewDataSource {
/// Number of Section
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
/// Non-Optional
/// NumberOfItemsInSection
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
<#code#>
}
/// Non-Optional
/// CellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
<#code#>
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
/// Cell Size
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width: CGFloat = view.frame.size.width * cellMultiplier
let height: CGFloat = view.frame.size.height * cellMultiplier
let size: CGSize = CGSize(width: width, height: height)
return size
}
}
UICollectionViewDataSource의 numberOfItemsInSection과 cellForItemAt은 이제부터 채워보자.
그전에 cell에 들어갈 Data Model부터 생성
//
// CollectionViewCellViewModel.swift
import Foundation
import UIKit
struct CollectionViewCellViewModel {
let name: String
let backgroundColor: UIColor
}
그리고 위에서 만들었던 MyCollectionViewCell.swift에 다음과 같은 코드를 추가한다.
func configure(with viewModel: CollectionViewCellViewModel) {
contentView.backgroundColor = viewModel.backgroundColor
label.text = viewModel.name
}
이를 통해 CollectionViewCellViewModel의 name과 backgroundColor를 Cell에 적용해준다.
다시 ViewController.swift로 이동해 CollectionViewCellViewModel 배열을 만들어 주자.
private var viewModels: [CollectionViewCellViewModel] = [
CollectionViewCellViewModel(name: "Red", backgroundColor: .systemRed),
CollectionViewCellViewModel(name: "Orange", backgroundColor: .systemOrange),
CollectionViewCellViewModel(name: "Yellow", backgroundColor: .systemYellow),
CollectionViewCellViewModel(name: "Green", backgroundColor: .systemGreen),
CollectionViewCellViewModel(name: "Blue", backgroundColor: .systemBlue),
CollectionViewCellViewModel(name: "Purple", backgroundColor: .systemPurple),
]
데이터까지 만들었으니 DataSource의 메서드를 마저 채워주자.
/// Non-Optional
/// NumberOfItemsInSection
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
viewModels.count
}
/// Non-Optional
/// CellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: MyCollectionViewCell.identifier,
for: indexPath
) as? MyCollectionViewCell else {
fatalError()
}
cell.configure(with: viewModels[indexPath.row])
return cell
}
cellForItemRowAt의 cell.configure(with: viewModels [indexPath.row])를 통해 cell을 업데이트해 준다.
끝~!
전체코드
ViewController.swift
//
// ViewController.swift
import UIKit
import SnapKit
class ViewController: UIViewController {
private var viewModels: [CollectionViewCellViewModel] = [
CollectionViewCellViewModel(name: "Red", backgroundColor: .systemRed),
CollectionViewCellViewModel(name: "Orange", backgroundColor: .systemOrange),
CollectionViewCellViewModel(name: "Yellow", backgroundColor: .systemYellow),
CollectionViewCellViewModel(name: "Green", backgroundColor: .systemGreen),
CollectionViewCellViewModel(name: "Blue", backgroundColor: .systemBlue),
CollectionViewCellViewModel(name: "Purple", backgroundColor: .systemPurple),
]
let cellMultiplier: CGFloat = 0.5
// Create UICollectionView
private let collectionView: UICollectionView = {
// Configure Layout
var layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .black
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
configureLayout()
configureCollectionView()
}
// SetUp AutoLayout with SnapKit
func configureLayout() {
view.addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.width.equalToSuperview()
make.height.equalTo((view.frame.size.height / 5 ) * 3)
make.top.leading.equalTo(view.safeAreaLayoutGuide)
}
}
func configureCollectionView() {
// Attach CollectionView Delegate & DataSource
collectionView.delegate = self
collectionView.dataSource = self
// Regist Cell
collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.identifier)
}
}
extension ViewController: UICollectionViewDelegate {
}
extension ViewController: UICollectionViewDataSource {
/// Number of Section
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
/// Non-Optional
/// NumberOfItemsInSection
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
viewModels.count
}
/// Non-Optional
/// CellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: MyCollectionViewCell.identifier,
for: indexPath
) as? MyCollectionViewCell else {
fatalError()
}
cell.configure(with: viewModels[indexPath.row])
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
/// Cell Size
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width: CGFloat = view.frame.size.width * cellMultiplier
let height: CGFloat = view.frame.size.height * cellMultiplier
let size: CGSize = CGSize(width: width, height: height)
return size
}
}
MyCollectionViewCell.swift
//
// MyCollectionViewCell.swift
//
import Foundation
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
static let identifier = "MyCollectionViewCell"
private let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.textAlignment = .center
label.font = .systemFont(ofSize: 25, weight: .semibold)
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
// Congifure Label
contentView.addSubview(label)
contentView.layer.cornerRadius = 6
contentView.layer.borderWidth = 1.5
contentView.layer.borderColor = UIColor.quaternaryLabel.cgColor
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
label.frame = contentView.bounds // label의 프레임을 cell의 바운드와 같게 조정
}
func configure(with viewModel: CollectionViewCellViewModel) {
contentView.backgroundColor = viewModel.backgroundColor
label.text = viewModel.name
}
}
Auto Carousel Effect를 구현하다가 빠르게 써보았다.
'iOS' 카테고리의 다른 글
iOS) Buttom Sheet - UISheetPresentationController (0) | 2022.10.13 |
---|---|
iOS) Carousel Effect 배너 구현하기 (Card 레이아웃, 자동 스크롤) with UICollectionView (0) | 2022.10.12 |
iOS) Error - Add Transport Security has blocked a cleartext HTTP connection to { ~ } since it is insecure .. (0) | 2022.10.05 |
iOS) Naver 지도 SDK 사용하기 (0) | 2022.10.05 |
iOS) 스토리보드 없이 개발 준비하기 (0) | 2022.10.03 |
- Total
- Today
- Yesterday
- Algorithm
- Custom Detent
- crud
- BOJ 10866
- Stack
- 1406 에디터
- Card CollectionVIew
- sheetPresentationController
- BOJ 17413
- Sheet Height
- bottom sheet
- UICollectionView banner
- BOJ 10799
- Gradient View
- BOJ 10808
- 요시푸스
- Carousel Effect
- BOJ 17298
- BOJ 10809
- NaverMaps
- CAGradientLayer
- git
- BOJ 10820
- swift
- github
- ios
- BOJ 1935
- autolayout
- 2023 회고
- UICollectionView Error
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |