본문 바로가기

프로그래밍/iOS

UICollectionView에 대해 알아보자.

1. UICollectionView가 무엇인가?

  • 정렬 된 데이터 항목 모음을 관리하고 사용자 지정 가능한 레이아웃을 사용하여 표시하는 개체

  • 컬렉션 뷰는 저장된 DataSource 개체에서 데이터를 가져온다.

  • DataSource의 경우 CollectionView의 데이터 및 User Interface에 대한 업데이트를 간단하고 효율적으로 관리함.

  • Supplementary View는 UITableView의 Header와 비슷한 역할을 한다.

2. 컬렉션뷰와 관련된 클래스 및 프로토콜

  • UICollectionView : 사용자에게 보여질 Collection 형태의 뷰

  • UICollectionViewCell : UICollectionView instence에 제공되는 데이터를 화면에 표시하는 역할을 담당

  • UICollectionReusableView : Cell의 재사용

  • UICollectionViewFlowLayout : CollectionView를 위한 디폴트 클래스로, 그리드 스타일로 셀들을 배치하도록 설계되어있다. scrollDirection 프로퍼티를 통해 수평 및 수직 스크롤을 지원한다.

  • UICollectionViewLayoutAttributes : CollectionView 내의 지정된 아이템의 레이아웃 관련 속성을 관리한다.

  • UICollectionViewDataSource 프로토콜 :CollectionView에 필요한 데이터 및 뷰를 제공하기 위한 기능을 정의한 프로토콜이다.

  • UICollectionViewDelegate 프로토콜 : CollectionView에서 아이템의 선택 및 강조 표시를 관리하고 해당 아이템에 대한 작업을 수행할 수 있는 기능을 정의한 프로토콜이다.

  • UICollectionViewDelegateFlowLayout 프로토콜 : UICollectionViewLayout 객체와 함께 그리드 기반 레이아웃을 구현하기 위한 기능을 정의한 프로토콜이다.

3. 사용 예시

1. LabelCollectionViewCell을 만들고 Xib 파일도 만들어 준다.

import UIKit

class LabelCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var labelName: UILabel!
    @IBOutlet weak var descriptionLabel: UILabel!
    override func awakeFromNib() {
        super.awakeFromNib()
        labelName.layer.cornerRadius = 8.0
        labelName.clipsToBounds = true
    }
}

2. LabelViewContoller를 만들고 viewDidLoad에 delegate dataSource cell 설정을 해준다.

class LabelViewController: UIViewController {
    var labels = [Label]()
    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView.delegate = self
        self.collectionView.dataSource = self
        self.collectionView.register(UINib(nibName: "LabelCollectionViewCell", bundle: .main), forCellWithReuseIdentifier: "LabelCollectionViewCell")
    }
}

3. extension을 사용 안하고 프로토콜을 추가해줘도 되지만 코드를 읽기 쉽게 하기 위해 extension을 해서 프로토콜을 구현하였다.

extension LabelViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return labels.count // 전체 데이터의 개수를 반환한다. Section 별로 만들 수 있는데, 현재는 1개의 섹션만 사용하기 때문에 바로 return을 해주었다.
/*
만약 여러개의 Section을 사용할 경우
switch(section) {
case 1:
   return sectionOneCount;
case 2:
   return sectionTwoCount;
}
이런식으로 분기를 준다.
*/
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// Cell에 데이터를 주는 것이다. indexPath는 해당 셀이 몇 번째 셀인지 나타내는 것이다.
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LabelCollectionViewCell", for: indexPath) as? LabelCollectionViewCell else {
            return UICollectionViewCell()
        }
        cell.labelName.text = labels[indexPath.row].name
        cell.descriptionLabel.text = labels[indexPath.row].description
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Cell의 크기를 지정하는 함수이다.
        return CGSize(width: collectionView.frame.width, height: 60)
    }
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Cell이 터치 될 경우 발생하는 이벤트이다.
        openDetailView(label: labels[indexPath.row])
    }
}
  • 현재 코드는 작성자가 필요한 함수만 가져왔다. Apple Developer Document에서 필요한 것을 찾아서 구현하는 것을 추천한다.

[참고 자료]

 

Apple Developer Documentation

 

developer.apple.com