관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 1. CollectionView (컬렉션 뷰) - UICollectionViewFlowLayout 본문

iOS 응용 (swift)

[iOS - swift] 1. CollectionView (컬렉션 뷰) - UICollectionViewFlowLayout

jake-kim 2021. 7. 16. 02:00

1. CollectionView (컬렉션 뷰) - UICollectionViewFlowLayout

2. CollectionView (컬렉션 뷰) - UICollectionViewFlowLayout을 이용한 CarouselView (수평 스크롤 뷰)

3. CollectionView (컬렉션 뷰) - custom layout (grid, pinterest 레이아웃 구현)

4. CollectionView (컬렉션 ) -실전 사용 방법 (FlowLayout, CustomLayout, binary search, cache)


FlowLayout, 정적 cell을 갖은 collectionView

CollectionView에 사용될 mock data 준비

struct CollectionViewData {
    static let data = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
}

커스텀 CollectionView 정의

class MyCollectionView: UICollectionView {
    // Nothing todo
}

커스텀 CollectionViewCell 정의

  • Cell의 id 값 정의
  • cell에 들어갈 item UI들은 contentView.addSubview()로 collectionView에 추가
  • item UI들의 laytout들을 설정
import UIKit
import SnapKit

class MyCollectionViewCell: UICollectionViewCell {

    static var id: String {
        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
    }

    var dataLabel: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)

        configure()
    }

    required init?(coder: NSCoder) {
        fatalError("Not implemented required init?(coder: NSCoder)")
    }

    private func configure() {
        dataLabel = UILabel()
        dataLabel.font = UIFont.systemFont(ofSize: 32)
        dataLabel.textColor = .label
        dataLabel.textAlignment = .center

        contentView.addSubview(dataLabel)
        dataLabel.snp.makeConstraints { make in
            make.edges.equalTo(safeAreaLayoutGuide)
        }
    }
}

CollectionView 적용

  • CollectionView와 dataSource 준비
class ViewController: UIViewController {

    private var myCollectionView: MyCollectionView!
    private let dataSource = CollectionViewData.data
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }    
    
}
  • collectionView 초기화 (viewDidLoad에서 호출)
    • CollectionViewLayer 객체를 만든 후 값 세팅
    • CollectionView(frame:collectionViewLayout:)으로 컬렉션뷰 초기화
    • CollectionView 레이아웃 설정
    private func configure() {

        let collectionViewLayer = UICollectionViewFlowLayout()
        collectionViewLayer.sectionInset = UIEdgeInsets(top: 5.0, left: 7.0, bottom: 5.0, right: 7.0)
        collectionViewLayer.minimumLineSpacing = 5
        collectionViewLayer.minimumInteritemSpacing = 1

        /// MyCollectionView()로 단순히 초기화하면 에러가 나므로 MyCollectionView(frame:collectionViewLayout:) 초기화 사용
        /// 만약 collectionViewLayer에 UICollectionViewLayout() 그대로 넣으면 `cellForItemAt`가 불리지 않으므로 주의
        myCollectionView = MyCollectionView(frame: .zero, collectionViewLayout: collectionViewLayer)
        myCollectionView.backgroundColor = .lightGray
        view.addSubview(myCollectionView)

        myCollectionView.snp.makeConstraints { make in
            make.top.equalTo(120)
            make.left.right.bottom.equalToSuperview().inset(40)
        }
    }
  • Cell 등록 (viewDidLoad에서 호출)
    private func registerCollectionView() {
        myCollectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.id)
    }
  • delegate, dataSource 할당
    private func setupCollectionViewDelegate() {
        myCollectionView.dataSource = self
        myCollectionView.delegate = self
    }
  • delegate, dataSource 구현
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    /// sizeForItemAt
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return UICollectionViewFlowLayout.automaticSize
    }

    /// numberOfItemsInSection
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource.count
    }

    /// cellForItemAt
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.id, for: indexPath) as! MyCollectionViewCell
        cell.dataLabel.text = dataSource[indexPath.item]
        return cell
    }
}

* source code: https://github.com/JK0369/CollectionViewExample

Comments