> 순서대로 정렬된 데이터 항목들을 관리하고, 이를 **사용자 정의 가능한 레이아웃**으로 표시하기 위한 클래스
> 유연하고 다양한 형태의 데이터 항목을 효과적으로 보여주고, 상호작용이 가능한 컬렉션 레이아웃을 제공하는 UI 컴포넌트
<br><br>
```swift
@MainActor
class UICollectionView : UIScrollView
```
<br>
>**@MainActor**
>기본적으로 UI 업데이트는 메인 스레드에서 이루어져야 한다. 그렇지 않으면 화면 갱신과 관련된 작업에서 예기치 않은 동작이 발생할 수 있다. `@MainActor`는 메인 스레드에서만 해당 코드 블록이 실행되도록 보장하는 역할을 한다.
<br><br>
## UICollectionView와 관련 개념들
### 개요
<br>
![[supplementary_view.png|center||600]]
<div style="text-align:center"><span style="color:gray;">공식문서에 있는 사진인데 대체 어디서 들고온 사진일까 TRPG인가 재밌겠다</span></div>
<br>
1. **data source 관리가 아주 중요함**
- `UICollectionView`를 UI에 추가할 때 해당 컬렉션 뷰와 관련된 **데이터를 효과적으로 관리하는 것**이 가장 중요함
- 데이터는 주로 data source 객체에서 가져오는데, 이 객체는 컬렉션 뷰의 `dataSource` 속성에 저장됨
- **`UICollectionViewDiffableDataSource`** 객체를 사용하면 컬렉션 뷰의 데이터 및 UI 업데이트를 간편하게 관리할 수 있음
- 또는 **`UICollectionViewDataSource`** 프로토콜을 채택하여 커스텀 data source 객체를 만들 수도 있음
2. **컬렉션뷰의 구성 요소: 아이템과 셀**
- 컬렉션 뷰의 데이터는 개별 아이템으로 구성되며, 이를 그룹화하여 섹션으로 표시할 수 있음
- **아이템 = 표시하려는 데이터의 가장 작은 단위**
- e.g. 사진 앱에서는 이미지 하나가 아이템이 될 수 있음
- 컬렉션 뷰는 **셀** 즉, `UICollectionViewCell` 클래스의 객체를 사용하여 화면에 아이템을 표시함
- 이 셀은 data source에서 구성하고 제공함
3. **supplementary view(보조 뷰)**
- 컬렉션 뷰는 셀 외에도 다양한 유형의 보조 뷰를 사용하여 데이터를 표시할 수 있음
- e.g. 위 이미지와 같은 섹션 헤더
- 보조 뷰는 선택 사항이며, 컬렉션 뷰의 **layout 객체**가 이러한 뷰의 배치를 정함
4. **아이템 순서 = 화면에 표시되는 순서**
- 컬렉션 뷰를 사용하면 화면에 표시되는 아이템의 순서가 data source에 저장된 아이템의 순서와 일치하도록 조절할 수 있음
- `UICollectionViewDiffableDataSource`가 이 프로세스를 자동으로 처리해줌
- 커스텀 data source를 사용하는 경우 컬렉션에 데이터를 추가, 삭제 또는 재배열할 때`UICollectionView`의 메소드를 사용하면 됨
- 이로써 data source에 변경이 발생하면 해당 변경사항을 컬렉션 뷰에 반영하는 일련의 작업을 단순화하고 효율적으로 처리할 수 있음
5. **선택된 아이템을 관리하는 방법**
- 컬렉션 뷰 객체를 사용하여 선택된 아이템을 관리함
- 여기에 대해서는 컬렉션 뷰가 관련된 델리게이트 객체와 함께 작동함
<br><br><br>
### 🖼️ 레이아웃을 지정하는 방법
> layout 객체를 통해 컬렉션 뷰의 레이아웃을 결정하고, 이를 동적으로 변경하거나 트랜지션을 통해 유연하게 조작할 수 있다.
<br>
##### 1. **layout 객체란**
- layout 객체는 컬렉션 뷰의 콘텐츠를 시각적으로 정렬하는 역할을 함
- `UICollectionViewLayout` 클래스의 하위 클래스로, 컬렉션 뷰 내부의 **모든 셀 및 보조 뷰의 구성과 위치를 정의함**
- layout 객체가 위치를 정의하지만, **해당 정보를 실제로 뷰에 적용하는 역할은 안 함**
- data source는 컬렉션 뷰에게 어떤 셀이나 보조 뷰가 필요한지 알려주고, 컬렉션 뷰는 이 정보를 바탕으로 해당 뷰들을 만드는데, 이때 만들어진 뷰를 화면에 어떻게 배치할지에 대한 정보, 즉 레이아웃 정보를 layout 객체가 제공함
##### 2. **레이아웃 지정 방법**
- 보통 컬렉션 뷰를 생성할 때 layout 객체를 지정하지만, 동적으로 컬렉션 뷰의 레이아웃을 변경할 수도 있음
- layout 객체는 `collectionViewLayout` 속성에 저장됨
- 이 속성을 직접 설정하면 변경 사항이 즉시 적용되지만, 애니메이션 없이 적용됨 (그냥 띡)
- 변경 사항을 애니메이션으로 적용하려면 `setCollectionViewLayout(_:animated:completion:)` 메소드를 호출하면 됨
##### 3. **상호작용 및 제스처 인식 방법**
- 제스처 인식이나 터치 이벤트에 의한 트랜지션을 만들려면, `startInteractiveTransition(to:completion:)` 메소드를 사용하여 layout 객체를 변경하면 됨
- 사용자의 제스처나 터치 이벤트에 의한 트랜지션은 시작, 진행, 그리고 완료 단계로 구성됨
- 트랜지션이 진행되는 동안 임시로 사용되는 intermediate layout 객체를 생성하여 트랜지션의 진행 상황을 추적함
- 이벤트 처리 코드가 트랜지션이 완료되었다고 판단하면, `finishInteractiveTransition()` 또는 `cancelInteractiveTransition()` 메소드를 호출하여 intermediate layout 객체를 제거하고 최종 target layout 객체를 적용함
<br><br><br>
### 🔄 셀과 보조 뷰를 사용하는 방법
>data source는 셀과 보조 뷰의 내용과 생김새를 정의하고, 컬렉션 뷰는 이러한 정보를 활용하여 화면에 아이템을 효과적으로 표시한다. 중요한 점은 뷰의 재사용을 최적화하기 위해 dequeue 메소드를 사용하고, 뷰를 dequeue 하기 전에 등록(registration) 과정을 통해 뷰의 생성 방법을 알려주어야 한다는 점이다.
<br>
##### 1. **data source 객체를 통해 정의**
- 컬렉션 뷰의 data source 객체는 아이템의 내용과 해당 내용을 표시하기 위한 뷰를 제공함
- 컬렉션 뷰가 처음으로 콘텐츠를 로드할 때, 화면에 표시될 각 아이템에 대한 뷰를 data source에 요청함
- 컬렉션 뷰는 data source가 재사용을 위해 표시해둔 뷰 객체의 큐나 리스트를 유지하고 있음
- **코드에서 새로운 뷰를 명시적으로 생성하는 대신, 뷰를 dequeue(재사용)해서 씀**
##### 2. **뷰 dequeue하기**
- 요청된 뷰의 유형(셀 or 보조 뷰)에 따라 2개의 메소드 중 적절한 것을 통해 dequeue 함
- `dequeueReusableCell(withReuseIdentifier:for:)`: 컬렉션 뷰의 아이템에 대한 셀을 얻기 위해 사용
- `dequeueReusableSupplementaryView(ofKind:withReuseIdentifier:for:)`: layout 객체에서 요청한 보조 뷰를 얻기 위해 사용
##### 3. **뷰 등록하기**
- 위 메소드를 호출하기 전에 해당 뷰가 아직 존재하지 않는다면, 뷰를 생성하는 방법을 컬렉션 뷰에 알려줘야 함
- 컬렉션 뷰에 클래스 또는 nib 파일을 등록함으로써 알려줄 수 있음
- **`register(_:forCellWithReuseIdentifier:)`** 메소드를 통해 셀 등록 가능
- 등록 과정의 일부로, 뷰의 목적을 식별하는 **reuse identifier** 문자열을 지정함
- 나중에 뷰를 dequeue 할 때 사용됨
##### 4. **뷰 구성 및 반환 순서**
- data source 메소드에서 적절한 뷰를 dequeue한 후, 해당 뷰의 내용을 구성하고 컬렉션 뷰에 반환함
- 컬렉션 뷰는 layout 객체로부터 레이아웃 정보를 얻은 후, 해당 정보를 뷰에 적용하고 화면에 표시함
<br><br>
<br>
### 📲 Data Prefetching
>Data Prefetching은 셀이 표시되기 전에 필요한 데이터를 미리 가져오는 기술로, 특히 네트워크 요청과 같이 비용이 큰 작업에 유용하며, Cell Prefetching과 함께 사용하면 컬렉션 뷰의 반응성을 향상시킬 수 있다.
<br>
컬렉션 뷰는 두 가지 Prefetching 기술을 제공한다.
##### 1. Cell Prefetching
- Cell Prefetching은 셀이 실제로 필요한 시점보다 먼저 셀을 준비해둠
- default로 활성화됨
- e.g. 그리드 레이아웃에서 새로운 셀 행이 필요한 경우, 셀들은 화면에 표시되기 전에 미리 요청됨
- Cell Prefetching으로 인해 셀 렌더링이 여러 번의 작업을 거쳐 수행되므로 더 부드러운 스크롤을 제공할 수 있게 됨
##### 2. Data Prefetching
- Data Prefetching은 네트워크 요청 처럼 셀의 데이터 로딩에 비용이 많이 드는 작업에 유용함
- `UICollectionViewDataSourcePrefetching` 프로토콜을 따르는 객체를 `prefetchDataSource` 속성에 할당하여 셀에 대한 Data Prefetching이 필요한 시점에 미리 알림을 받을 수 있음
<br><br><br>
### 👆🏻 아이템을 이동시키는 방법
##### 1. 사용자 상호작용 기반 아이템 이동
- 컬렉션 뷰는 사용자 상호작용을 기반으로 아이템을 이동시킬 수 있는 기능을 제공함
- 일반적으로 컬렉션 뷰의 아이템 순서는 data source에 의해 정의됨
- 사용자가 아이템을 재배열할 수 있도록 하면, **gesture recognizer**를 구성해서 아이템과의 상호작용을 추적하고 해당 아이템의 위치를 업데이트할 수 있음
##### 2. 아이템 이동 과정
- 우선 컬렉션 뷰의 `beginInteractiveMovementForItem(at:)` 메소드를 호출함
- gesture recognizer가 터치 이벤트를 추적하는 동안, `updateInteractiveMovementTargetPosition(_:)` 메소드를 호출하여 터치 위치의 변화을 보고함
- 제스처 추적이 끝나면, `endInteractiveMovement()` 또는 `cancelInteractiveMovement()` 메소드를 호출하여 상호작용을 마치고 컬렉션 뷰를 업데이트함
##### 3. 이동 중 레이아웃 업데이트 및 애니메이션
- 사용자 상호작용 중에는 현재 아이템의 위치를 반영하기 위해 컬렉션 뷰가 동적으로 레이아웃을 무효화함
- 아무것도 하지 않으면 기본 레이아웃 동작이 아이템을 자동으로 재배열하지만, 원한다면 레이아웃 애니메이션을 커스텀할 수 있음
- 상호작용이 끝나면 컬렉션 뷰는 새로운 아이템 위치로 data source 객체를 업데이트함
##### 4. default gesture recognizer
- `UICollectionViewController` 클래스는 컬렉션 뷰에서 항목을 재배열할 수 있는 default gesture recognizer를 제공함
- 이 gesture recognizer를 사용하려면, 컬렉션 뷰 컨트롤러의 `installsStandardGestureForInteractiveMovement` 속성을 `true`로 설정하면 됨
<br><br>
<br>
### ⏺️ Interface Builder 속성
##### 1. Items
- **프로토타입 셀의 개수**를 나타냄
- 스토리보드에서 구성할 프로토타입 셀의 수를 제어함
- 컬렉션 뷰는 최소한 하나의 셀을 가져야 하며, 서로 다른 유형의 콘텐츠를 표시하거나 동일한 콘텐츠를 다르게 표시하기 위해 여러 셀을 가질 수 있음
##### 2. Layout
- 사용할 레이아웃 객체를 선택함
- `UICollectionViewFlowLayout` 객체와 사용자가 정의한 커스텀 layout 객체 중에서 선택할 수 있음
- Flow 레이아웃이 선택된 경우, 컬렉션 뷰의 콘텐츠의 스크롤 방향을 구성하고 Flow 레이아웃에 헤더와 푸터 뷰가 있는지 여부를 설정할 수 있음
- 헤더 및 푸터 뷰를 활성화하면 스토리보드에 재사용 가능한 뷰가 추가되며, 이를 사용하여 헤더 및 푸터 내용을 구성할 수 있음
- Flow 레이아웃이 선택된 경우, 컬렉션 뷰의 Size Inspector에는 Flow 레이아웃 메트릭을 구성하기 위한 추가 속성이 포함되어 있음. 이러한 속성을 사용하여 셀의 크기, 헤더 및 푸터의 크기, 셀 간의 최소 간격, 그리고 각 섹션 주위의 여백을 구성할 수 있음
- 커스텀 레이아웃이 선택된 경우, 사용할 `UICollectionViewLayout` 서브 클래스를 지정해야 함
<br><br><br>
---
**참고 문서**
- https://developer.apple.com/documentation/uikit/uicollectionview
- https://developer.apple.com/documentation/swift/mainactor
- https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/layouts
**관련 포스트**
- [[UICollectionView의 주요 메서드]]
<br>
<br>
<br>
<br>