VesselWheel

UICollectionView의 UICollectionViewFlowLayout 본문

Xcode Study

UICollectionView의 UICollectionViewFlowLayout

JasonYang 2024. 1. 2. 18:31

통일성을 갖는 셀의 관리를 위해 UICollectionView를 사용한다. 

그중에서,

Flowlayout은 컬레션뷰에 종속된 셀의 간격, 여백 등을 조정할 수 있는 프로토콜이다. 

 

UICollectionViewFlowLayout으로 상세설정한 collectionView의 cell 모습

UI Peroperties를 선언

    // MARK: - UI Properties
	private lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(MenuCell.self, forCellWithReuseIdentifier: MenuCell.collectionViewCellIdentifier)
        collectionView.backgroundColor = .white
        
        return collectionView
    }()

1. 상기 코드는 `collectionView`라는 UI 요소를 생성하는 부분으로 `collectionView`는 `UICollectionView` 클래스의 인스턴스를 생성하여 초기화

 

2. `UICollectionViewFlowLayout`를 사용하여 컬렉션 뷰의 레이아웃을 설정

 - `collectionView`의 프로퍼티들을 설정한 후, `collectionView`를 반환하는 클로저로 정의되어 있고, 이 클로저는 `lazy` 키워드로 선언되어 처음으로 `collectionView`가 접근될 때 실행된다.

 

3. `collectionView`의 초기 프레임은 `.zero`로 설정하고 이후에 extension으로 관리하여 올바른 프레임이 설정하기로 한다.

 

4. `collectionView`의 `translatesAutoresizingMaskIntoConstraints` 프로퍼티는 `false`로 설정되어 있어, 오토레이아웃을 사용하여 위치와 크기를 지정할 수 있도록 한다.

 

5. `collectionView`의 `delegate`와 `dataSource`는 현재 클래스(또는 다른 클래스)의 인스턴스를 자체 할당하여 해당 프로토콜의 메서드를 구현할 수 있도록 한다.

 

6. `collectionView`의 `register(_:forCellWithReuseIdentifier:)` 메서드를 사용하여 `MenuCell` 클래스를 등록합니다. 이렇게 등록된 셀은 재사용 식별자를 사용하여 컬렉션 뷰에서 재사용될 수 있다. 

 

7. `collectionView`의 배경색은 `.white`로 설정, 이렇게 설정된 `collectionView`는 UI 요소로 사용되며, 해당 컬렉션 뷰를 생성하고 초기화하는 코드

 

여기서 의문난 점!

프로퍼티를 생성하면서 클로져로 캡슐화 한 이유는?

더보기

이 코드에서 `collectionView`를 클로저 형태로 캡슐화한 이유는 다음과 같습니다:

1. 초기화 과정을 캡슐화: `collectionView`를 클로저로 정의함으로써 초기화 과정을 한 곳에 모아둘 수 있습니다. 클로저 내부에서 필요한 설정들을 모두 처리하고, 최종적으로 초기화된 `collectionView`를 반환합니다. 이는 코드의 가독성을 향상시키고, 초기화 관련 코드를 재사용하기에도 용이합니다.

 

2. 지연 초기화 (Lazy initialization): `collectionView`를 `lazy` 키워드로 선언하고, 클로저 형태로 초기화함으로써, `collectionView`가 처음으로 접근되는 시점에서 초기화됩니다. 이는 필요한 시점에서만 `collectionView`를 생성하고 메모리를 절약할 수 있습니다. 만약 `collectionView`가 사용되지 않는 경우에는 초기화되지 않습니다.

 

3. 커스텀 설정 및 초기화 과정: 클로저 내부에서는 `UICollectionViewFlowLayout`를 사용하여 레이아웃을 설정하고, `delegate`, `dataSource`, `register(_:forCellWithReuseIdentifier:)` 등의 메서드를 호출하여 커스텀 설정 및 초기화를 수행합니다.

 

이는 `collectionView`의 초기화 과정을 편리하게 처리할 수 있도록 합니다. 따라서, 클로저 형태로 `collectionView`를 캡슐화함으로써 초기화 과정을 효율적으로 관리하고, 필요한 시점에서만 초기화되도록 할 수 있습니다.

 

extension으로 UICollectionVieDelegateFlowLayout에서 상세 설정

UICollectionViewDelegate에서 지원하는 선택 가능한 레이아웃 매소드들

 

MenuView 익스텐션에서 구현한 FlowLayout

// MARK: - UICollectionViewDelegateFlowLayout

extension MenuView: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        return CGSize(width: 165, height: 70)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        
        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        
        return 30
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        
        return CGSize(width: 400, height: 15)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
        
        return CGSize(width: 400, height: 15)
    }
}

 

1. `sizeForItemAt`: 해당 메서드는 각 셀의 크기를 지정하는 역할을 하며, `IndexPath` 매개변수를 통해 각 셀의 인덱스 정보를 얻을 수 있고, `CGSize`를 반환하여 해당 셀의 가로 너비와 세로 높이를 지정할 수 있다. CGSize(width: 165, height: 70)

 

2. `insetForSectionAt`: 이 메서드는 섹션의 여백 (inset)을 지정하는 역할을 하며, `UIEdgeInsets`를 반환하여 섹션의 위쪽, 왼쪽, 아래쪽, 오른쪽 여백 값을 지정할 수 있다. UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

 

3. `minimumLineSpacingForSectionAt`: 해당 메서드는 섹션 내에서 아이템(셀) 사이의 최소한의 세로 간격을 지정하는 역할을 한다. `CGFloat` 값을 반환하여 아이템 사이의 간격을 조정할 수 있다. return 30

 

4. `referenceSizeForHeaderInSection`: 이 메서드는 섹션 헤더의 크기를 지정하는 역할을 하며, `CGSize`를 반환하여 섹션 헤더의 가로 너비와 세로 높이를 지정할 수 있다. CGSize(width: 400, height: 15)

 

5. `referenceSizeForFooterInSection`: 해당 메서드는 섹션 푸터의 크기를 지정하는 역할을 한다. `CGSize`를 반환하여 섹션 푸터의 가로 너비와 세로 높이를 지정할 수 있다. CGSize(width: 400, height: 15)

 

이렇게 `UICollectionViewDelegateFlowLayout` 프로토콜의 다양한 메서드를 구현하여 `MenuView`의 컬렉션 뷰의 레이아웃을 세밀하게 조정할 수 있다.

 

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