본문 바로가기

iOS

[iOS] Collection View APIs

728x90

Collection View APIs

  • collection view는 iOS 6에 처음 등장한 개념이다.
  • CollectionView에서 다루는 개념은 크게 세가지 이다.
    • 어떤 데이터를
    • 어떤 레이아웃에
    • 어떻게 보여줄 것인가?

→ 위의 세가지는 각각 아래의 API를 통해서 관리할 수 있다.

  • 데이터 : UICollectionViewDataSource
  • 레이아웃 : UICollectionViewLayout의 하위 클래스인 UICollectionFlowLayout
  • 렌더링 : UICollectionViewCell / UICollectionReusableView

 

iOS 13+

어떤 것이 달라졌는가?

  • 다크모드
  • AppDelegate, SceneDelegate
  • SwiftUI

… 등이 새로 추가 되었다.

여기서 가장 큰 변화 중 하나는 SwiftUI의 등장이다.

✨ SwiftUI

기존의 개발 환경(UIKit)에서는 각 OS에 따라서 다른 환경에서 개발을 진행 했어야 했다.

  • UIKit → iOS/iPad
  • AppKit → macOS
  • WatchKit → watch

 

그러나, 이에 불편함을 느낀 애플이 (not me) 새로운 개발 환경을 만들었다고 보면 된다.

UIKit, AppKit, WatchKit etc ..

→ 이것들을 베이스로 만든 것이 SwiftUI (그래서 이 안에 UIKit코드 + AppKit코드 + WatchKit 코드 .. )

  • UIKit : **클래스**를 기반으로 만들어짐
  • SwiftUI : 객체들이 모두 **구조체**로 만들어짐
    • 그래서 iOS 13 이후로 나온 기술들이 구조체를 기반으로 만들어진 것들이 많다.

 

CollectionView APIs

~iOS 12

→ iOS 13 이전

 

iOS 13

→ iOS 13 등장

🚨 iOS 14에서 새롭게 등장한 것이 있는데 .. 🚨

 

iOS 14+

  • 이것들을 활용하면 Diffable Data Source, Compositional Layout을 좀 더 쉽게 사용할 수 있다.
    • 이 부분들은 너무 깊게 공부하기 보다 List어쩌구 키워드가 나오면 iOS 14 이후로 나온 개념이라고 생각하면 된다.
  • 13에서 나온 개념을 기반으로 새로운 기능인 Section Snapshot, List Configuration 등을 만들어냈다.
  • List Configuration은 Compositional Layout 기반으로 만들어졌고
  • 컬렉션 뷰를 테이블 뷰처럼 사용할 수 있다.
    • 섹션 별로 다른 레이아웃을 설정할 수 있으며
    • 스와이프 제스처 등의 기능을 구현할 수 있다.

 

UICollectionLayoutListConfiguration

  • ListConfiguration을 사용하면 테이블 뷰와 유사한 모양을 컬렉션 뷰에서 구현할 수 있다.
    • UICollectionViewCompositionalLayout
    • NSCollectionLayoutSection (→ 섹션 별 레이아웃을 설정할 때 사용)
    → 이 두가지를 기반으로 구성되어 있다.

🟢 유연한 레이아웃 대응이 가능하고

🟢 self-sizing 기능을 통해서 셀 높이를 수동으로 계산할 필요가 없다.

 

Components of a list

  • List 형태의 레이아웃을 만들기 위한 구조체
  • 모든 섹션에 동일한 configuartion을 적용할 수도 있고 각 섹션마다 다른 레아웃을 적용할 수도 있다.
  • 그 외로 separator, header, footer, swipe 등의 처리도 가능하다.

→ 정말 딱 .. 테이블 뷰처럼 동작 … 테이블 뷰가 곧 사라질 것이라는 것이지 ..

 


실습

🔥 테이블 뷰의 시스템 셀처럼 컬렉션뷰에서 제공하는 리스트 속성을 이용해서 테이블 뷰를 만들어보자. 🔥

어떻게 만들 수 있을까?

기존의 동작 원리

ListConfiguration이 나오기 전에 동작 원리는 아래와 같다.

  • 데이터 구조 설계 (+ 데이터 생성)
  • CollectionView에 등록
  • CollectionView의
    • 어떤 데이터를 보여줄지
    • 어떤 레이아웃으로 보여줄지
    → 등을 설정

 

ListConfiguration 사용 동작 원리

위에서 적은 동작 원리와 비슷하다.

  • 데이터 구조 설계 (+ 데이터 생성) ✅
  • CollectionView에 등록
  • CollectionView의
    • 어떤 데이터를 보여줄지 ✅
    • 어떤 레이아웃으로 보여줄지 ✅
    → 등을 설정

위에서 ✅ 로 표시한 부분은 동일하게 구현해야 하는 부분이고 그렇지 않은 부분도 있다.ListConfiguration에서 새롭게 생긴 속성들로 몇가지 과정이 필요가 없는데, 구현 과정을 살펴보면서 알아보자 😎

 

실제로 구현해보자.

1. 데이터 생성

메모 앱의 경우 DB에 저장된 데이터를 받아오므로 이를 받아서 저장할 배열을 만들어준다.

private var tasks: Results<Memo>!

2. UICollectionViewDataSource

  • 어떤 데이터를 보여줄 것인지
  • 어떤 셀에 렌더링 할 것인지

→ 를 UICollectionViewDataSource에서 관리할 수 있다.

extension ListCollectionViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return tasks.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let item = tasks[indexPath.row]
        let cell = collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
        return cell
    }
}

위의 코드에서 기존의 것과 다른 점은 cellForItemAt부분이다.

  • dequeueConfiguredReusableCell 을 사용해서 컬렉션 뷰에 보여줄 셀을 지정한다.
  • 여기에 필요한 파라미터는 세가지이다.
    • using
      • 어떤 셀을?
    • for
      • 어디에? (인덱스 - 위치)
    • item
      • 어떤 데이터를?

각각에 들어가는 정보를 표현하면 아래와 같다.

  • 어떤 셀을?
  • var cellRegistration: UICollectionView.CellRegistration<UICollectionViewListCell, Memo>!
  • 어디에?
    • 각 인덱스
  • 어떤 데이터?
    • Realm Database에 저장되어 있는 객체를 담은 배열
  • let item = tasks[indexPath.row]

3. 레이아웃 설정

어떤 레이아웃을 사용할것인가?

기존의 UICollectionViewFlowlayout가 아니라, UICollectionViewCompositionalLayout 의 list 속성을 사용할 것이므로 컬렉션 뷰의 레이아웃을 이 속성을 사용해서 만들어주면 된다.

    lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    
    let configuration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
    private lazy var layout = UICollectionViewCompositionalLayout.list(using: configuration)

4. cell의 렌더링

cellRegistration = UICollectionView.CellRegistration(handler: { cell, indexPath, itemIdentifier in
    var content = cell.defaultContentConfiguration()
            
    content.text = itemIdentifier.memoTitle
    content.secondaryText = itemIdentifier.memoContent
    content.image = itemIdentifier.count < 2 ? UIImage(systemName: "heart") : UIImage(systemName: "heart.fill")
            
    cell.contentConfiguration = content
})

cell의 defaultContentConfiguration 인스턴스를 담은 content를 선언하고

이를 통해서 셀을 꾸며줄 수 있다.