1. 첫 번째 학습 내용: Collection View (컬렉션뷰)

Class

UICollectionView

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

class UICollectionView : UIScrollView

When you add a collection view to your user interface, your app's main job is to manage the data associated with that collection view. The collection view gets its data from the data source object, stored in the collection view’s [**dataSource](https://developer.apple.com/documentation/uikit/uicollectionview/1618091-datasource) property. For your data source, you can use [UICollectionViewDiffableDataSource](https://developer.apple.com/documentation/uikit/uicollectionviewdiffabledatasource) object**, which provides the behavior you need to simply and efficiently manage updates to your collection view's data and user interface. Alternatively, you can create a custom data source object by adopting the [UICollectionViewDataSource](https://developer.apple.com/documentation/uikit/uicollectionviewdatasource) protocol.

Data in the collection view is organized into individual items, which you can group into sections for presentation. An item is the smallest unit of data you want to present. For example, in a photos app, an item might be a single image. The collection view presents items onscreen using a cell, which is an instance of the [UICollectionViewCell](https://developer.apple.com/documentation/uikit/uicollectionviewcell) class that your data source configures and provides.

Cells and Supplementary Views

The collection view’s data source object provides both the content for items and the views used to present that content. When the collection view first loads its content, it asks its data source to provide a view for each visible item.

The collection view maintains a queue or list of view objects that the data source has marked for reuse. Instead of creating new views explicitly in your code, you always dequeue views.

There are two methods for dequeueing views. The one you use depends on which type of view has been requested:

  • Use the [dequeueReusableCell(withReuseIdentifier:for:)](https://developer.apple.com/documentation/uikit/uicollectionview/1618063-dequeuereusablecell) to get a cell for an item in the collection view.
  • Use the [dequeueReusableSupplementaryView(ofKind:withReuseIdentifier:for:)](https://developer.apple.com/documentation/uikit/uicollectionview/1618068-dequeuereusablesupplementaryview) method to get a supplementary view requested by the layout object.

Data Prefetching

Collection views provide two prefetching techniques you can use to improve responsiveness:

  • Cell prefetching prepares cells in advance of the time they are required. When a collection view requires a large number of cells simultaneously—for example, a new row of cells in grid layout—the cells are requested earlier than the time required for display. Cell rendering is therefore spread across multiple layout passes, resulting in a smoother scrolling experience. Cell prefetching is enabled by default.
  • Data prefetching provides a mechanism whereby you are notified of the data requirements of a collection view in advance of the requests for cells. This is useful if the content of your cells relies on an expensive data loading process, such as a network request. Assign an object that conforms to the [UICollectionViewDataSourcePrefetching](https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching) protocol to the [prefetchDataSource](https://developer.apple.com/documentation/uikit/uicollectionview/1771768-prefetchdatasource) property to receive notifications of when to prefetch data for cells.

둘 중에 뭐 쓴거지?
네트워크 리퀘스트이니 Data prefetching인가?
그냥 fetch아니고 prefetching해야하는 건가? 이유는?

WWDC 2020

컬렉션뷰 셀 vs 테이블뷰 셀
컬렉션뷰를 학습하면서 앞서 배웠던 테이블뷰와 비슷한 점이 많지 않았나요? 그렇다면 컬렉션뷰 셀과 테이블뷰 셀에는 어떠한 차이점이 있는지 알아볼까요?

  • 테이블뷰 셀의 구조는 콘텐츠 영역과 액세서리뷰 영역으로 나뉘었지만, 컬렉션뷰 셀은 배경뷰와 실제 콘텐츠를 나타내는 콘텐츠뷰로 나뉘었습니다.
  • 테이블뷰 셀은 기본으로 제공되는 특정 스타일을 적용할 수 있지만 컬렉션뷰 셀은 특정한 스타일이 따로 없습니다.
  • 테이블뷰 셀은 목록형태로만 레이아웃 되지만, 컬렉션뷰 셀은 다양한 레이아웃을 지원합니다.

데이터소스

컬렉션뷰 데이터소스 객체는 컬렉션뷰와 관련하여 가장 중요한 객체이며, 필수로 제공해야 합니다. 컬렉션뷰의 콘텐츠(데이터)를 관리하고 해당 콘텐츠를 표현하는 데 필요한 뷰를 만듭니다. 데이터소스 객체를 구현하려면 UICollectionViewDataSource 프로토콜을 준수하는 객체를 만들어야 합니다. 그리고 데이터소스 객체는 최소한 collectionView(_:numberOfItemsInSection:)과 collectionView(_:cellForItemAt:) 메서드를 구현해야 하며 나머지 메서드는 선택사항입니다.

델리게이트

컬렉션뷰 델리게이트 프로토콜은 컬렉션뷰에서 셀의 선택 및 강조표시를 관리하고 해당 셀에 대한 작업을 수행할 수 있는 메서드를 정의합니다. 이 프로토콜의 메서드는 모두 선택사항입니다.

iOS 앱 프로그래밍

2. 두 번째 학습 내용: UICollectionViewFlowLayout

UICollectionViewFlowLayout 클래스를 사용하면 컬렉션뷰의 셀을 원하는 형태로 정렬할 수 있습니다. 플로우 레이아웃은 레이아웃 객체가 셀을 선형 경로에 배치하고 최대한 이 행을 따라 많은 셀을 채우는것을 의미합니다. 현재 행에서 레이아웃 객체의 공간이 부족하면 새로운 행을 생성하고 거기에서 레이아웃 프로세스를 계속 진행합니다.

플로우 레이아웃 구성 단계

  1. 플로우 레이아웃 객체를 작성해 컬렉션뷰의 레이아웃 객체로 지정합니다.
  2. 셀의 너비와 높이를 구성합니다.
  3. 필요한 경우 셀의 간격을 조절합니다.
  4. 원할 경우 섹션 헤더 혹은 섹션 푸터를 크기를 지정합니다.
  5. 레이아웃의 스크롤 방향을 설정합니다.

플로우 레이아웃 속성 변경하기

플로우 레이아웃 객체는 콘텐츠의 모양을 구성하기 위해 여러 가지 프로퍼티를 제공합니다. 이 프로퍼티에 적절한 값을 설정하면 모든 셀에 동일한 레이아웃이 적용됩니다. 예를 들면 플로우 레이아웃 객체의 itemSize 프로퍼티를 사용하여 셀의 크기를 설정할 경우 모든 셀의 크기가 동일하게 적용됩니다.

플로우 레이아웃의 셀 크기 지정하기

컬렉션뷰의 모든 셀이 같은 크기인 경우 플로우 레이아웃 객체의 itemSize의 프로퍼티에 적절한 너비와 높이 값을 할당합니다. 각각의 셀마다 다른 크기를 지정하려면 컬렉션뷰 델리게이트에서 collectionView:layout:sizeForItemAtIndexPath: 메서드를 구현해야 합니다. 메서드의 매개변수로 제공하는 인덱스 경로 정보를 사용해 해당 셀의 크기를 반환할 수 있습니다.

문제점/고민한점 → 해결방안

현재 사태: 컬렉션뷰 셀이 화면에 아예 안나옴

그리드로 넘어가면 컬렉션뷰가 나와야 하는데
그냥 희멀건 화면만 나온다

해결 방법 by 제임스 👏
→ 셀 크기 지정 & 오토레이아웃 해줘야 함

Tip : 플로우 레이아웃은 대부분 프로퍼티의 기본값을 가지고 있습니다. 하지만 셀의 너비와 높이는 모두 0으로 지정되어 있기 때문에 셀의 크기는 지정해주어야 합니다. 그렇지 않을 경우 셀의 너비와 높이의 기본값이 0이기 때문에 셀이 화면에 보이지 않을 수도 있습니다.

(지금 내 상황이 딱 이렇다 ^.^
시뮬레이터에 아무것도 안보임 케ㅋ)

셀 예상(Estimated) 크기 지정

iOS 8 이전의 버전에서는 셀의 크기를 조정하는 방법이 크게 두 가지 있었습니다. 첫 번째 방법은 UICollectionViewFlowLayout 클래스의 itemSize프로퍼티를 이용해 모든 셀을 같은 크기로 설정하는 방법이고, 두 번째 방법은 UICollectionViewDelegateFlowLayout 프로토콜의 collectionView(_:layout:sizeForItemAt:) 메서드를 사용해 셀마다 다른 크기를 지정하는 방법이 있었습니다. iOS 8부터는 새로운 방법이 하나 추가되었습니다. 셀에 오토레이아웃을 적용하고(앞의 두 가지 방법에도 셀에 오토레이아웃을 적용할 수는 있습니다) 셀 스스로 크기를 결정한 후 이를 UICollectionViewLayout 객체에 알려줍니다. 이 방법을 사용하려면 estimatedItemSize 프로퍼티를 사용해 대략적인 셀의 최소 크기를 미리 알려줍니다.

let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
flowLayout.estimatedItemSize = CGSize(width: 50.0, height: 50.0)

collectionView.collectionViewLayout = flowLayout

셀 크기 지정해주려고 했는데 안됨

해결 방법: 이미지 사이즈 width, height constraint 지정해줘야 함
셀 사이즈는 셀 사이즈고
UIImageView는 사이즈 스토리보드에서 정해줄 수 있음!
Thanks to 제임스 👏

셀 사이즈 지정해주는 방법

func setupFlowLayout() {
            let flowLayout = UICollectionViewFlowLayout()
            flowLayout.sectionInset = UIEdgeInsets.zero
            flowLayout.minimumInteritemSpacing = 10
            flowLayout.minimumLineSpacing = 10
            
            let halfWidth = UIScreen.main.bounds.width / 2
            flowLayout.itemSize = CGSize(width: halfWidth * 0.8, height: halfWidth * 0.8)
            self.collectionView.collectionViewLayout = flowLayout
        }

[iOS] UICollectionView 톺아보기 - 4

올라프 조언

컨테이너 뷰컨에서
네트워크 요청할 것

테이블뷰, 컬렉션뷰는 이벤트를 전달해주는 역할만 하기

네트워크는 최대한 적게 요청하는게 좋음!
셀에서 바로 데이타 불러오는건 안 좋음
매번 셀 만들때마다 불러오니까.

일단은 하나의 뷰컨에
두개의 테이블뷰 컬렉션뷰 놔도 되고
세그먼트에 따라 보여주고 말고를 결정해주면 됨

컨테이너뷰 컨트롤러도 어려운 개념임 ^.ㅠ

컨테이너뷰 컨트롤러의 좋은 점
로직을 분리할 수 있음
e.g. 테이블뷰 컨트롤러는 테이블뷰만 가지고 있음

로직을 짤줄 알아야지
나누는건 그 다음 일임

뷰컨 하나에다 다 때려박아도 되니까
네트워크 흐름을 이해해보고
중복되는 부분이 어딘지 확인해보고

베스트는
컬렉션뷰 하나를 쓰고
셀을 바꾸든가
레이아웃을 바꾸든가 하는 방법

profile
iOS Developer

0개의 댓글