iOS (스파르타)

UICollectionView - Basic반 수업 공부

가애야 2024. 8. 13. 21:25

UICollectionView 란,,!

공식문서 설명 상으로는

정렬된 데이터 항목 컬렉션을 관리하고 사용자 정의 가능한 레이아웃을 사용하여 이를 표시하는 객체라고 되어있다.

@MainActor
class UICollectionView : UIScrollView

UIScrollView를 상속받는다.

 

컬렉션뷰의 데이터는 개별 항목으로 구성되며, 이를 프레젠테이션을 위해 섹션으로 그룹화 할 수 있다.

항목은 표시하려는 가장 작은 데이터 단위. 예를 들어, 사진앱에서 항목은 단일 이미지 일 수 있다.

컬렉션뷰는 데이터소스가 구성하고 제공하는 클래스의 인스턴스인 셀을 사용하여 화면에 항목을 표시한다. UICollectionViewCell

 

셀 외에도 컬렉션 뷰는 다른 유형의 뷰를 사용하여 데이터를 표시할 수 있고, 이러한 보충뷰는 예를들어 개별 셀과 분리되어 있지만 여전히 정보를 전달하는 섹션 헤더 및 푸터일 수 있다, 보충뷰에 대한 지원은 선택사항이며 컬렉션 뷰의 레이아웃 개체에 의해 정의되며, 이는 뷰의 배치를 정의하는 역할을 한다.

 

UICollectionViewDiffableDataSource 개체는 이 프로세스를 자동으로 관리합니다.

사용자 지정 데이터 소스를 사용하는 경우 컬렉션에서 데이터를 추가, 삭제 또는 재정렬할 때마다의 메서드를 사용하여 해당 셀을 삽입, 삭제 및 재정렬합니다.

 

선택한 항목을 관리하려면 컬렉션 뷰 개체를 사용할 수도 있습니다. 하지만 이 동작의 경우 컬렉션 뷰는 연관된 delegate개체와 함께 작동합니다.

 

 


 

 

주요 구성 요소

UICollectionView: 컬렉션 뷰 자체를 나타내는 클래스

UICollectionViewCell: 컬렉션 뷰의 각 셀을 나타내는 클래스. 셀은 컬렉션 뷰에 표시되는 단위 요소이다.

UICollectionViewLayout: 컬렉션 뷰의 레이아웃을 정의하는 클래스. 기본적으로 제공되는 'UICollectionViewFlowLayout'을 사용하거나, 사용자 정의 레이아웃을 정의할 수 있다.

UICollectionViewDataSource: 컬렉션 뷰에 데이터를 제공하는 프로토콜이다. 'UITableViewDataSource'와 유사하게, 셀의 개수 및 각 셀의 콘텐츠를 설정하는 역할을 한다.

UICollectionViewDelegate: 셀 선택 등의 상호작용을 처리하는 프로토콜이다.

 

컬렉션 뷰 만드는 방법~!

뷰 컨트롤러의 뷰에 UICollectionView를 추가하고 적절한 제약조건을 설정해준다.

UICollectionView를 생성하고 화면에 추가하려면, ViewController 클래스 안에서 컬렉션 뷰를 초기화하고 설정해줘야 한다.

import UIKit

class ViewController: UIViewController {

    // 1. 컬렉션 뷰 생성
    var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 2. 레이아웃 설정
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 100, height: 100) // 셀 크기 설정
        layout.minimumInteritemSpacing = 10 // 셀 간 간격 설정
        layout.minimumLineSpacing = 10 // 행 간 간격 설정

        // 3. 컬렉션 뷰 초기화
        collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
        collectionView.backgroundColor = .white // 컬렉션 뷰 배경색 설정

        // 4. 데이터 소스 및 델리게이트 설정
        collectionView.dataSource = self
        collectionView.delegate = self

        // 5. 컬렉션 뷰 셀 등록
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")

        // 6. 컬렉션 뷰를 뷰에 추가
        self.view.addSubview(collectionView)
    }
}

이렇게 하면 일단 오류가 뜬다

dataSource랑 delegate부분에 ㅎ

 

 

fix를 누르면 코드들이 추가되고 오류는 사라지는데

코드 위쪽에 추가가 되고~

그렇게 진행해도 되고 밑에 extension으로 빼서 작성해줘도 되는데

이유는 몰까! 모냐면! 그건 밑에서 다시 할게여,,

 

그리고 데이터소스 및 델리게이트 설정

컬렉션 뷰가 데이터를 표시할 수 있도록 데이터소스와 델리게이트 메서드를 구현해야 한다.

extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {

    // 섹션당 아이템 수를 반환하는 메서드
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20 // 20개의 셀을 표시
    }

    // 각 셀을 구성하는 메서드
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue // 셀 배경색을 파란색으로 설정
        return cell
    }

    // 셀을 선택했을 때 호출되는 메서드 (선택 사항)
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Selected item at \(indexPath.row)")
    }
}

 

 

전체적으로 코드를 보면

import UIKit

class ViewController: UIViewController {

    // 1. 컬렉션 뷰 생성
    var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 2. 레이아웃 설정
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 100, height: 100)
        layout.minimumInteritemSpacing = 10
        layout.minimumLineSpacing = 10

        // 3. 컬렉션 뷰 초기화
        collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
        collectionView.backgroundColor = .white

        // 4. 데이터 소스 및 델리게이트 설정
        collectionView.dataSource = self
        collectionView.delegate = self

        // 5. 컬렉션 뷰 셀 등록
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")

        // 6. 컬렉션 뷰를 뷰에 추가
        self.view.addSubview(collectionView)
    }
}

extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }
    
    // 콘솔창에 찍는 코드
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Selected item at \(indexPath.row)")
    }
}

 

 

extension을 사용해 UICollectionViewDataSource와 UICollectionViewDelegate 메서드를 정의하는 것과, 직접 클래스 내부에서 메서드를 작성하는 것의 차이는 코드의 구조화 방식과 가독성에 있다. 이 둘은 기능적으로 동일하지만, 코드 관리와 확장성 측면에서 차이가 있다.

 

클래스 내부에 작성하는 경우

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

    var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // 컬렉션 뷰 설정 코드
    }

    // UICollectionViewDataSource 메서드
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }

    // UICollectionViewDelegate 메서드
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Selected item at \(indexPath.row)")
    }
}

모든 코드가 한 곳에 있으므로 작은 프로젝트에서는 이해하기 쉽고 관리가 간편하다.

클래스에 많은 메서드가 추가될 경우, 코드가 길어져 가독성이 떨어질 수 있다.

클래스가 너무 많은 책임을 가지게 되어 응집도가 낮아질 수 있다. 이는 유지보수와 확장에 어려움을 줄 수 있다.

 

extension을 사용하여 분리하는 경우

class ViewController: UIViewController {

    var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // 컬렉션 뷰 설정 코드
    }
}

// MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }
}

// MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Selected item at \(indexPath.row)")
    }
}

코드 가독성이 좋아진다. 각 프로토콜에 해당하는 메서드를 별도의 extension으로 분리함으로써 클래스의 본래 역할(즉, 뷰 컨트롤러의 기본로직)을 더 명확하게 할 수 있다.

관리가 용이하다. 프로토콜별로 코드가 분리되므로 특정 기능에 집중하여 코드의 모듈화를 촉진한다.

코드가 더 잘 분리되어 있어 새로운 프로토콜을 구현하거나 기존 프로토콜을 수정할 때 관리가 쉬워 유지보수성이 좋다.

하지만 프로젝트가 작거나 간단한 경우, 코드가 여러곳에 분리되어있어 오히려 코드를 이해하기 어려울 수 있다.

 

 

UICollectionView는 기본적으로 수직!으로 정렬된다.

 

위에서 작성한 코드를 시뮬 돌리면 한 행에 3개의 셀이 들어가고 그 밑으로 정렬이 되는데

UICollectionViewFlowLayout()을 사용해서 이런 화면이 나온것이당!

UICollectionViewFlowLayout이게 제일 많이 사용되는 기본 레이아웃이고

다른 레이아웃을 사용할 수도 있는데

UICollectionViewCompositionalLayout 이 레이아웃을 사용하면 섹션별로 다른 레이아웃을 설정하거나 다양한 형태의 셀 배치를 쉽게 구성할수 있단다!

https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout

 

UICollectionViewCompositionalLayout | Apple Developer Documentation

A layout object that lets you combine items in highly adaptive and flexible visual arrangements.

developer.apple.com

UICollectionViewCompositionalLayout 에 관련된 공식문서 임당

얘는 iOS 13 부터 도입된 레이아웃 시스템~

 

다양한 서드파티 라이브러리도 존재한다

예를들어

PinterestLayout: Pinterest 스타일의 그리드 레이아웃을 구현하는 데 사용할 수 있다.

WaterfallLayout: 물이 떨어지는 듯한 배치(Waterfall layout) 스타일을 구현할 수 있다.

 

이러한 라이브러리들은 특별한 형태의 레이아웃을 더 쉽게 구현할 수 있게 해준다.

 

 

 

휴,, 일단 정리 끝!

사용방법은 더더 연습해봐야 할거 같지만

정리하면서 대충 여태 사용했던 것들이 이해가 갈락말락했고

이제 테이블뷰랑 무슨 차이점이 있는지도 함 찾아서 정리할 예정!

 

내용의 도움은 공식문서와 지티피요 ㅎㅋ 지씨 고마워~!

https://developer.apple.com/documentation/uikit/uicollectionview

 

UICollectionView | Apple Developer Documentation

An object that manages an ordered collection of data items and presents them using customizable layouts.

developer.apple.com