<h1><center> CollectionView - FlowLayout vs CompositionalLayout </center></h1> ###### title: `CollectionView - FlowLayout vs CompositionalLayout` ###### tags: `💻 TIL`, `CollectionView`, `UICollectionViewFlowLayout`, `CompositionalLayout` ###### date: `2023-11-15T10:39:33.284Z` > [color=#724cd1][name=데릭] > [Apple - UICollectionViewFlowLayout ](https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout) > [Apple - UICollectionViewCompositionalLayout](https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout) ## 개요 > UICollectionViewFlowLayout과 CompositionalLayout이 무엇인지, 차이점은 어떤게 있는지 학습해보자. > 둘 다 UICollectionViewLayout을 상속한다. ## UICollectionViewFlowLayout > 각 Section에 대한 Optional Header, Footer 뷰가 있는 Grid로 Item을 구성하는 레이아웃 객체이다. 컬렉션 뷰의 Item은 스크롤 방향에 따라 한 Column(스크롤 방향에 따라)에서 다음 Column으로 흐르며, 각 Column에는 가능한 많은 셀이 포함된다. - 셀의 크기는 같을 수도 있고 다를 수도 있다. 설정에 따라 다르다. Flow Layout은 컬렉션 뷰의 Delegate 객체와 함께 작동하여 각 Section과 Grid의 items, Header, Footer 크기를 결정한다. - Delegate를 사용하면 레이아웃을 동적으로 조절할 수 있다. 또한, 한 방향(vertical or horizontal)에서 고정 거리를 가지고(Width or Height가 고정되는것) 스크롤 가능한 거리를 측정하여 Content를 배치한다. 예를 들어, Vertical 스크롤 그리드에서 그리드의 콘텐츠의 width는 컬렉션 뷰의 width로 제한된다. 그러나, 콘텐츠 의 Height는 그리드의 Section, item 수에 맞춰 동적으로 조절된다. - Default: Vetical Scrolling - `scrollDirection`프로퍼티를 사용하여 스크롤 방향을 구성할 수 있다. 그리고 각 섹션에 고유한 Custom Header와 Footer가 있을 때, 뷰의 Header나 Footer를 구성하려면 Size를 0이 아닌 값으로 구성해야한다. ```swift let layout = UICollectionViewFlowLayout() let sectionSpacing: CGFloat = 20 let itemSpacing: CGFloat = 8 // 수직 스크롤이라는 가정 하에, rowCount는 몇개의 행을 사용할지를 저장한 변수 let width: CGFloat = UIScreen.main.bounds.width - (itemSpacing * (rowCount-1)) - (sectionSpacing * 2) let itemWidth: CGFloat = width / rowCount // 각 item의 크기 설정 (아래 코드는 정사각형을 그린다는 가정) layout.itemSize = CGSize(width: itemWidth, height: itemWidth) // 스크롤 방향 설정 layout.scrollDirection = .vertical // Section간 간격 설정 layout.sectionInset = UIEdgeInsets(top: sectionSpacing, left: sectionSpacing, bottom: sectionSpacing, right: sectionSpacing) // item간 간격 설정 layout.minimumLineSpacing = itemSpacing // 최소 줄간 간격 (수직 간격) layout.minimumInteritemSpacing = itemSpacing // 최소 행간 간격 (수평 간격) collectionView.collectionViewLayout = layout // collectionView에 설정한 Layout 인스턴스를 할당 ``` ## UICollectionViewCompositionalLayout > 적응력이 뛰어나고 유연한 시각적 배열로 Item을 결합할 수 있는 레이아웃 객체이다. <br> > Layout을 별도의 시각적 Grouping으로 나누는 하나 이상의 Section으로 구성된다. > 각 섹션은 표시하려는 데이터의 가작 단은 단위인 개별 Item Group으로 구성된다. > 그룹은 Item을 Horizontal Row, Vertical Column 또는 Custom 배열로 배치할 수 있다. ![image](https://hackmd.io/_uploads/rk78cBz4p.png) > UICollectionViewCompositionalLayout의 Layout 구성 ## 둘의 차이점 ||UICollectionViewFlowLayout|UICollectionViewCompositionalLayout| |---------------------|--------|---------| | **구조적 차이** | |구조를 더 추상화하고, 그룹화된 섹션과 아이템의 레이아웃을 정의하는 데에 중점을 둔다.| | **동적 레이아웃** ||런타임에서 동적으로 레이아웃을 조절할 수 있는 기능을 제공한다. 조금 더 유연하게 대응할 수 있다. | | **API 설계** | |함수형 프로그래밍 스타일을 기반으로 한 API를 사용하여 레이아웃을 정의한다. | | **코드의 간결성** || 선언적으로 정의할 수 있기 때문에 코드가 더 간결하고 읽기 쉬워지는 경향이 있다.| **선언적 정의 예시** ```swift let flowLayout = UICollectionViewFlowLayout() flowLayout.scrollDirection = .vertical flowLayout.itemSize = CGSize(width: 100, height: 100) flowLayout.minimumInteritemSpacing = 10 flowLayout.minimumLineSpacing = 10 let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: 300, height: 300), collectionViewLayout: flowLayout) ``` > UICollectionViewFlowLayout ```swift let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.25)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) let layout = UICollectionViewCompositionalLayout(section: section) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) ``` > UICollectionViewCompositionalLayout