register():UICollectionView에서 사용할 셀 클래스를 등록하는 역할. 어떤 종류의 셀을 표시할 것인지 알려주는 역할
dataSource:데이터 소스를 테이블 뷰에 할당하여 테이블 뷰가 데이터를 어디서 가져와서 어떻게 표시할 지를 알려주기 위해 설정 (UICollectionView가 속한 컨트롤러에 "UICollectionViewDataSource" 프로토콜을 추가해야 한다. 해당 프로토콜을 따르기 위해서는 collectionView()라는 메서드가 필요하다.)
delegate: 테이블 뷰의 동작 및 사용자 상호 작용(셀 선택, 스크롤 등…)을 제어하기 위해 사용. (UICollectionView가 속한 컨트롤러에 "UICollectionViewDelegateFlowLayout" 프로토콜을 추가해야 한다.)
<UICollectionViewFlowLayout>
그리드 형태의 레이아웃을 쉽게 구현할 수 있도록 도와주는 클래스
셀의 크기, 간격, 그룹화 등을 쉽게 설정할 수 있다.
[Method & Property]
.scrollDirection:그리드가 수직적인지 수평적인지 지정할 수 있는 프로퍼티
등… 프로퍼티 및 메서드 추가로 공부해보기!
//
// UICollectionViewTest.swift
// UIKit-Study
//
// Created by Kyungsoo Lee on 2023/09/30.
//
import UIKit
class UICollectionViewTest: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
// MARK: - UICollectionView
private lazy var uiCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
// frame을 .zero로 사용하여 CGRect(0, 0, 0, 0)으로 초기화하고, 이후 오토 레이아웃을 통해 layout을 설정한다.
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .white
// UICollectionView가 속한 컨트롤러에 "UICollectionViewDataSource" 프로토콜을 추가해야 한다.
// "UICollectionViewDataSource" 프로토콜을 따르기 위해선 collectionView()를 반드시 선언해야 한다.
collectionView.dataSource = self
// UICollectionView가 속한 컨트롤러에 "UICollectionViewDelegateFlowLayout" 프로토콜을 추가해야 한다.
collectionView.delegate = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
// MARK: - UICollectionViewDataSource 메서드
// 특정 섹션에 속하는 아이템(셀)의 총 개수를 반환한다.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
// 각 셀을 생성하고 구성하기 위해 호출
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// dequeueReusableCell()을 통해 재사용 가능한 셀을 얻는다. 셀이 없으면 재사용 큐에 셀을 생성한다.
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = .red
return cell
}
// MARK: - UICollectionViewDelegateFlowLayout
// CollectionView에 들어갈 Item에 size에 대한 정보
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 50, height: 50)
}
// CollectionView에 들어갈 셀 사이의 minimum spacing에 대한 정보
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
// CollectionView에 들어갈 각 Item의 Inset(여백) 대한 정보
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
}
// MARK: - viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = .systemGray
// 뷰 추가(아직 layout 설정 안된 상태)
self.view.addSubview(self.uiCollectionView)
setLayout()
}
// MARK: - UICollectionView 제약 조건
private func setUICollectionViewLayout() {
let uiCollectionViewConstraint = [
uiCollectionView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
uiCollectionView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
uiCollectionView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8),
uiCollectionView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6)
]
NSLayoutConstraint.activate(uiCollectionViewConstraint)
}
// MARK: - 전체 제약조건 설정
// 컴포넌트들의 레이아웃을 설정한다
private func setLayout() {
// 프레임 기반의 레이아웃을 비활성화 하여 오토 레이아웃을 기반으로 설정할 수 있도록 한다.
// UICollectionView 제약조건 설정
setUICollectionViewLayout()
}
}
// UIKit으로 짠 화면을 SwiftUI로 바로 볼 수 있게 해주는 코드
import SwiftUI
@available(iOS 13.0.0, *)
struct UICollectionViewTestControllerPreview: PreviewProvider {
static var previews: some View {
UICollectionViewTest().toPreview()
}
}