Bibi's DevLog 🤓🍎

코드로 UICollectionView 만들기 본문

📱🍎 iOS

코드로 UICollectionView 만들기

비비 bibi 2022. 5. 12. 16:18

코드로 UICollectionView 만들기

1. 컬렉션뷰의 셀 역할을 할 UICollectionViewCell을 만들고 내용 넣기

import UIKit

class HomeYourRecommandViewCell: UICollectionViewCell {

    static let identifier = "HomeYourRecommandViewCell"

    private let menuImageViewSize: CGFloat = 100

    private let menuImageView: UIImageView = {
        var imageView = UIImageView()
        imageView.backgroundColor = .cyan
        imageView.layer.cornerRadius = 50
        return imageView
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setUI()
        setConstraint()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setUI()
        setConstraint()
    }

    private func setUI() {
        self.addSubview(menuImageView)
    }

    private func setConstraint() {
        configureMenuImageViewConstraint()
    }

    private func configureMenuImageViewConstraint() {
        menuImageView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            menuImageView.topAnchor.constraint(equalTo: self.topAnchor),
            menuImageView.widthAnchor.constraint(equalToConstant: menuImageViewSize),
            menuImageView.heightAnchor.constraint(equalToConstant: menuImageViewSize),
            menuImageView.centerXAnchor.constraint(equalTo: self.centerXAnchor)
        ])
    }
}

2. 뷰컨트롤러에 UICollectionView 선언하고, Datasource와 Delegate 지정하기

  • UICollectionView는 UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())와 같이 레이아웃을 함께 지정해 초기화해야 에러가 나지 않음
    • collectionViewLayoutUICollectionViewLayout()말고!! UICollectionViewFlowLayout()로 넣어야 함!!
    • 가로 스크롤을 위해서는 flowLayout.scrollDirection을 .horizontal 로 지정 후 생성
  • extension을 통해 UICollectionViewDatasource를 반드시 확장
    • 컬렉션뷰의 기본 셋팅 가능
  • extension을 통해 UICollectionViewDelegateFlowLayout을 확장
    • 컬렉션뷰의 셀 크기를 지정할 수 있음
  • 뷰컨트롤러의 viewDidLoad()에 .delegate = self, .datasource = self, .register()는 필수적임. 확장한 datasource와 delegate를 연결하는 작업.
//
//  HomeViewController.swift
//  starbuckst
//
//  Created by Bibi on 2022/05/09.
//

import UIKit

class HomeViewController: UIViewController {
    static let identifier = "HomeViewController"

    private let yourRecommandView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

    override func viewDidLoad() {
        super.viewDidLoad()

        self.yourRecommandView.dataSource = self
        self.yourRecommandView.delegate = self
        self.yourRecommandView.register(HomeYourRecommandViewCell.self, forCellWithReuseIdentifier: HomeYourRecommandViewCell.identifier)

        setViews()
        setViewConstraints()
    }

    private func setViews() {
        self.view.addSubview(yourRecommandView)
    }


    private func setViewConstraints() {
        configureYourRecommandViewConstraint()
    }
    private func configureYourRecommandViewConstraint() {
        yourRecommandView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            yourRecommandView.topAnchor.constraint(equalTo: contentView.topAnchor),
            yourRecommandView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            yourRecommandView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            yourRecommandView.heightAnchor.constraint(equalToConstant: 100)
        ])
    }

}


extension HomeViewController: UICollectionViewDataSource {

  // 만들 셀의 갯수
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }

  // 만들 셀 정의 - 1.에서 만든 UICollectionViewCell 지정
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: HomeYourRecommandViewCell.identifier, for: indexPath) as? HomeYourRecommandViewCell else {
            return UICollectionViewCell()
        }
        cell.backgroundColor = .blue
        return cell
    }
}

extension HomeViewController: UICollectionViewDelegateFlowLayout {
  // 셀 크기 설정
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 200, height: 200)
    }
}

(선택) 헤더 만들기

UICollectionViewDataSource의 아래 메서드들 이용

  • 헤더가 될 뷰를
  • func collectionView(\_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
    • 헤더를 설정하는 메서드
  • func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
    • 헤더의 너비와 높이를 설정하는 메서드
  • 위 메서드 구현 이후 마찬가지로 viewDidLoad()에서 self.collectionView.register(MainViewHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MainViewHeader.identifier)

VC extension 부분

extension HomeViewController: UICollectionViewDataSource {

    // ...

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { // 헤더 설정
        if kind == UICollectionView.elementKindSectionHeader {
            if let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: HomeYourRecommandHeader.identifier, for: indexPath) as? HomeYourRecommandHeader {
                header.backgroundColor = .brown
                return header
            }
        }
        return UICollectionReusableView()
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { // 섹션의 헤더 너비와 높이 설정
        let width = collectionView.frame.width
        let height: CGFloat = 100
        return CGSize(width: width, height: height)
    }

}

헤더가 될 뷰

  • UICollectionReusableView로 구현
import Foundation  
import UIKit

class MainViewHeader: UICollectionReusableView {

static let identifier = "MainViewHeader"

override init(frame: CGRect) {
    super.init(frame: frame)
    setUI()
    setConstraints()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    setUI()
    setConstraints()
}

private func setUI() {
// addSubview
}

private func setConstraints() {
// set constraints
}

}