Archive 문서로 알아보는 Collection View Basics

Archive 문서로 알아보는 Collection View Basics
Photo by Kelly Sikkema / Unsplash

들어가며

기본에 대해 확실히 짚고 넘어가기 위해 Archive된 문서인 Collection View Basics를 보고, 과거로 돌아가 Collection View의 concept을 이해해보자

Collection View

Collection View는 contents를 화면에 표시하기 위해 다양한 객체와 협력한다.

이 중 일부 객체는 custom 객체이기 때문에 이를 작성해 프레임워크에 알려야한다.

예를 들어 Collection View에 표시할 item 수를 알려주는 data source와 같은 객체를 제공해야한다.

Table View와 마찬가지로 Collection View는 앱의 객체와 협력을 통해 구현되는 data-oriented 객체이다.

코드를 작성하기 위해 Collection View의 작동 방식에 대해 알아보자

A Collection View Is a Collaboration of Objects

Collection view는 data와 data가 화면에 정렬 및 표시되는 방식의 역할을 분리하여 구현할 수 있도록 설계되어있다.

표시할 데이터에 대한 관리는 전적으로 app에 책임이 있지만 시각적인 표현(visual presentation)은 다양한 객체에 의해 관리된다.

아래의 표는1-1에는 UIKit CollectionView 클래스가 나열되어있으며, CollectionView 인터페이스를 구현할 때 수행하는 역할에 따라 클래스를 구성한다.

대부분의 클래스는 서브클래싱 할 필요없이 그대로 사용할 수 있도록 설계되었으므로 일반적으로 매우 적은 코드로 CollectionView를 구현할 수 있다.

제공된 동작(behavior)보다 다양한 동작을 구현하고 싶을 때는 서브클래스를 만들어 해당 동작을 제공할 수 있다.

Table 1-1  The classes and protocols for implementing collection views

Purpose

Classes/Protocols

Description

Top-level containment and management

UICollectionView

UICollectionViewController

A UICollectionView object defines the visible area for your collection view’s content. This class descends from UIScrollView and can contain a large scrollable area as needed. This class also facilitates the presentation of your data based on the layout information it receives from its layout object.

A UICollectionViewController object provides view controller–level management support for a collection view. Its use is optional.

Content management

UICollectionViewDataSource protocol

UICollectionViewDelegate protocol

The data source object is the most important object associated with the collection view and is one that you must provide. The data source manages the content of the collection view and creates the views needed to present that content. To implement a data source object, you must create an object that conforms to the UICollectionViewDataSource protocol.

The collection view delegate object lets you intercept interesting messages from the collection view and customize the view’s behavior. For example, you use a delegate object to track the selection and highlighting of items in the collection view. Unlike the data source object, the delegate object is optional.

For information about how to implement the data source and delegate objects, see Designing Your Data Source and Delegate.

Presentation

UICollectionReusableView

UICollectionViewCell

All views displayed in a collection view must be instances of the UICollectionReusableView class. This class supports a recycling mechanism in use by collection views. Recycling views (instead of creating new ones) improves performance in general and especially improves it during scrolling.

A UICollectionViewCell object is a specific type of reusable view that you use for your main data items.

Layout

UICollectionViewLayout

UICollectionViewLayoutAttributes

UICollectionViewUpdateItem

Subclasses of UICollectionViewLayout are referred to as layout objects and are responsible for defining the location, size, and visual attributes of the cells and reusable views inside a collection view.

During the layout process, a layout object creates layout attribute objects (instances of the UICollectionViewLayoutAttributes class) that tell the collection view where and how to display cells and reusable views.

The layout object receives instances of the UICollectionViewUpdateItem class whenever data items are inserted, deleted, or moved within the collection view. You never need to create instances of this class yourself.

For more information about the layout object, see The Layout Object Controls the Visual Presentation.

Flow layout

UICollectionViewFlowLayout

UICollectionViewDelegateFlowLayout protocol

The UICollectionViewFlowLayout class is a concrete layout object that you use to implement grids or other line-based layouts. You can use the class as-is or in conjunction with the flow delegate object, which allows you to customize the layout information dynamically.

표의 내용을 하나씩 살펴보자

Top-level containment and management

UICollectionView , UICollectionViewController

UICollectionView 객체는 Collection View의 콘텐츠에 대한 표시 영역(visible area)을 정의한다.

UICollectionView 의 선언부를 보면 알 수 있듯, UICollectionViewUIScrollView를 상속받아 스크롤 가능한(Scorollable) 영역을 포함할 수 있다.

또한 이 클래스는 layout객체에서 수신한 layout정보를 기반으로 데이터를 표시할 수 있다.

UICollectionViewController 객체는 Collection View에 대한 View Controller level의 관리를 할 수 있다. UICollectionViewController 의 사용이 강제되어있지는 않다.

Content Management

data source 객체는 Collection View와 관련된 가장 중요한 객체이며, 반드시 프레임 워크에 제공해야 하는 객체이다.

data source는 collection view의 contents를 관리하고, 해당 contents를 표시하는 데 필요한 view를 만든다.

data source 객체를 구현하려면 UICollectionViewDataSource protocol 을 준수하는 객체를 만들어야한다.

Collection View delegate 객체를 이용하면 Collection View에서 메시지를 가로채 View의 동작을 custom할 수 있다.

예를 들어 delegate 객체를 사용해서 Collection View에서 item 선택 및 highlighting된 것을 알 수 있다.

delegate 객체를 구현하려면 UICollectionViewDelegate protocol 을 준수하는 객체를 만들어야한다.

data source 객체와 달리 delegate 객체는 선택사항이다.

data source 및 delegate 객체를 구현하는 방법에 대한 자세한 내용은 data source 및 delegate 설계 문서에 있습니다.

iOS 13+

iOS 13 이상 버전부터 사용가능한 이 UICollectionViewDiffableDataSource 역시

UICollectionViewDataSource 의 서브 클래스이다.

이와 관련해서 Adcances in UI Data Sources WWDC 세션을 정리하는 시간을 다음 포스트에서 가져보도록 하겠습니다.

Presentation

Collection View에 표시되는 모든 view는 UICollectionReusableView 클래스의 인스턴스여야한다.

이 클래스는 collection view에서 사용중인 recycling mechanism을 지원한다.

새 view를 만드는 대신 view를 재활용하면 일반적으로 성능(performance)가 향상되며 특히 스크롤과 관련하여 성능이 향상된다.

UICollectionViewCell 객체는 주요 data item에 사용하는 재사용 가능한 view의 특정 타입이다.

UICollectionViewCell class의 선언부를 보면 UICollectionViewCell 이  UICollectionReusableView 의 서브클래스임을 알 수 있다.

Layout

UICollectionViewLayout 의 서브클래스는 layout 객체라고 하며 collection view내에서 cell과 재사용 가능한 view의 위치, 크기, 시각적인 속성을 정의하는 역할을 담당한다.

layout 프로세스 중에 layout 객체는 Collection View에 cell과 reusable view를 표시할 위치와 방법을 알려주는 레이아웃 속성 객체(UICollectionViewLayoutAttributes 클래스의 인스턴스)를 생성한다.

layout 객체는 Collection View내에서 data item이 삽입, 삭제 또는 이동할 때마다 UICollectionViewUpdateItem 클래스의 인스턴스를 수신한다.

이 클래스의 인스턴스를 직접 만들 필요는 없다.

layout  객체에 대한 자세한 내용은 이 문서에 있습니다.

Flow layout

UICollectionViewFlowLayout 클래스는 grid 또는 기타 line-based 레이아웃을 구현하는 데 사용하는 concrete layout객체이다.

이 클래스를 그대로 사용하거나 layout 정보를 동적으로 custom할 수 있는 flow delegate 객체와 함께 사용할 수 있다.

UICollectionView는 iOS6에서 추가된 뷰입니다.
UITableView에서 구현하기 어려웠던 여러 가지 레이아웃 커스터마이징 기능을 제공합니다. 별도로 레이아웃 서브클래스를 만들지 않고 UICollectionViewFlowLayout를 사용하는 것만으로도 기본적인 그리드 레이아웃을 구현할 수 있으며, 좀 더 세밀하게 레이아웃을 제어할 필요가 있을 땐 UICollectionViewLayout의 서브클래스를 만들어 구현하는 것도 가능합니다.

- UICollectionView를 이용한 LINE iOS 대화방 리팩토링 중 -

iOS13+

하지만 시간이 흐름에 따라 점차 복잡한 레이아웃들이 많이 생기게 되었고, Flow layout 으로도 복잡한 레이아웃을 구현하기 어려워짐에 따라 여러 Group을 Composition해서 layout을 구성할 수 있는  Compositional Layout이 등장하게 되었다.

iOS 13 이상 버전 부터 사용가능한 이 UICompositionalLayout 역시 UICollectionViewLayout 의 서브클래스이다.

Collection View의 초기 design이 data와 data가 화면에 정렬 및 표시되는 방식의 역할을 분리하여 design되었기 때문에 layout에 영향을 주는 구현체가 새로 나와도 영향을 주지 않고 확장되는 방식이 흥미로웠습니다.

Figure 1-1  Merging content and layout to create the final presentation

Figure 1-1은 Collection View와 연결된 핵심 객체간의 관계를 보여준다.

Collection View는 data source에서 표시할 cell에 대한 정보를 가져온다.

data source 및 delegate 객체는 앱에서 제공하는 custom 객체이며 cell 선택 및 highlight 표시를 포함해 contents를 관리하는데 사용된다.

layout 객체는 해당 cell이 속한 위치를 결정하고, 해당 정보를 하나 이상의 layout attributes 객체의 형태로 Collection View에 보내는 역할을 한다.

그러면 Collection View가 layout 정보를 실제 cell(및 다른 view)과 병합해 최종 visual presentation을 만든다.

Collection View 인터페이스를 만들 때는 UICollectionView 객체를 만들어야한다.

Collection View를 다른 모든 객체가 나오는 중앙 허브 라고 생각하면 된다.

해당 객체를 추가한 후에는 data source 또는 delegate와 같은 관련 객체를 configuration하기 시작할 수 있다.

모든 configuration은 Collection View 자체를 중심으로 이루어진다.

예를 들어 Collection View 객체를 만들지 않고는, layout 객체를 만들 수 없다.

Reusable Views Improve Performance

Collection View는 view recycling 메커니즘을 사용해 효율성을 높인다.

View가 화면 밖으로 이동하면 View에서 제거되고 삭제되는 대신 reuse queue에 배치된다. 새 contents가 화면에서 스크롤 되면 view가 reuse queue에서 제거되고, 새 contents로 용도가 변경된다.

이러한 recycling 및 reuse를 용이하게 하려면 모든 view가 UICollectionReusableView 의 클래스에서 파생되어야한다.

Collection View는 세 가지 타입의 재사용 가능한 가능한 view를 지원하며, 각 view에는 특정 용도가 있다.

Cell

cell은 Collection View의 주요 contents를 표시한다.

cell의 역할은 data source 객체의 단일 item에 대한 contents를 표시하는 것이다.

각 cell은 필요에 따라 contents를 표시하기 위해 subclass화 할 수 있는 UICollectionViewCell 의 인스턴스여야한다.

cell 객체는 선택 및 highlight 표시 상태 관리를 위한 기능을 제공한다.

cell에 highlight를 적용하려면 code를 작성해야한다.

관련 내용은 이 문서에 있습니다.

Supplementary views

Supplementary view는 Section에 대한 정보를 표시한다.

cell과 마찬가지로 Supplementary view역시 data driven(데이터 기반)이다.

cell과 달리 Supplementary view는 필수가 아니며사용 및 배치는 사용 중인 layout 객체에 의해 제어된다.

예를들어 Flow layout은 Header와 Footer를 Supplementary view로 지원한다.

Decoration view

Decoration view는 layout 객체가 전적으로 소유하며 data source 객체의 데이터에 연결되지 않는 말그대로 시각적인 장식이다.

예를 들어 layout 객체는 Decoration view를 이용해 custom background appearance를 구현할 수 있다.

table view와 달리  collection view는 cell 및 supplementary view에 특정 스타일을 적용하지 않는다. 대신 reusable view class는 사용자가 수정할 수 있는 빈 canvas이기 때문에 예를 들어 작은 view 계층을 작성하거나 이미지를 표시하거나 contents를 동적으로 그리는 데 사용할 수 있다.

data source 객체는 연결된 collection view에서 사용하는 cell 및 supplementary view를 제공할 책임이 있지만 data source 객체는 view를 직접 만들지 않는다.

view를 요청 받으면 data source는 collection view의 메서드를 사용해 원하는 타입의 view를 dequeue한다.

dequeue 프로세스는 reuse queue에서 view를 검색하거나 사용자가 제공한 class, nib 파일 또는 Storyboard를 사용해 새 view를 생성하여 유효한 view를 반환한다.

data source에서 view를 만들고 configuration하는 방법에 대한 자세한 내요은 이 문서에 있습니다.

The Layout Object Controls the Visual Presentation

layout 객체는 Collection View내에서 item 배치 및 시각적 스타일을 결정하는 역할을 한다.

data source 객체가 view와 실제 contents를 제공하지만 layout 객체는 해당 view의 크기, 위치 및 appearance 관련 속성을 결정한다.

이러한 책임의 분리를 통해 app에서 관리하는 data 객체를 변경하지 않고도 layout을 동적으로변경할 수 있다.

Collection View에서 사용하는 layout 프로세스는 app의 나머지 view에서 사용하는 layout 프로세스와 관련이 있지만 별개이다.

이 말은   layout 객체가 수행하는 작업을 부모 view 내에서 자식 view의 위치를 변경하는 데 사용되는 layoutSubViews 메서드와 혼동할 수 있다는 말입니다.
layout 객체는 실제로 해당 view를 소유하지 않기 때문에 관리하는 뷰를 직접 건드리지는 않습니다.

대신 Collection View에서 cell, Supplementary view 및 Decoration view의 위치, 크기 및 시각적 appearance를 설명하는 속성을 생성한다.

그 다음 이러한 속성을 실제 view객체에 적용하는 것은 Collection View의 작업이다.

Figure 1-2  The layout object provides layout metrics

layout 객체는 view의 크기와 위치만 제어하는 것이 아니다.

layout 객체는 transparency, 3D 공간에서의 변형, 다른 view 위 또는 아래의 visibility(있는 경우) 등 기타 view 관련 속성을 지정할 수 있다.

예를 들어 view를 서로 겹쳐서 배치하고 z순서를 변경하여 cell stack을 만들거나 transform을 사용해 원하는 축으로 회전할 수 있다.

layout객체가 Collection View에 대한 책임을 수행하는 방법에 대한 자세한 내용은 이 문서에 있습니다.

Collection Views Initiate Animations Automatically

Collection View는 fundamental level에서 animation을 지원한다.

item 또는 Section을 삽입(또는 삭제)하면 Collection View는 변경사항의 영향을 받는 모든 view에 자동으로 animation을 적용한다.

예를 들어 item을 삽입하면 일반적으로 insert 지점 이후의 item이 새 item을 위한 공간을 확보하기 위해 이동한다.

Collection View는 item의 현재 위치를 감지하고, insert이후 최종 위치를 계산할 수 있기 때문에 이러한 animation을 만들 수 있다.

따라서 각 item의 초기 위치에서 최종 위치까지 animation을 적용할 수 있다.

insert, delete 및 이동 작업에 animation을 적용하는 것 외에도 언제든지 layout을 무효화 하고 layout 속성을 강제로 다시 계산할 수 있다.

layout을 무효화하면 item에 직접 animation이 적용되지는 않으며, layout을 무효화하면 Collection View에서 item에 animation을 적용하지 않고 새로 계산된 위치에 item이 표시된다.

대신 custom layout에서 이 동작을 사용해 cell을 일정한 간격으로 배치하고 animation 효과를 만들 수 있다.

마무리

이상 Collection View Baics에 대한 정리였습니다.

아직 모르는 것이 많고 알아가는 과정입니다. 잘못된 것이 있다면 댓글로 남겨주신다면 감사하겠습니다! 😊

참고

Collection View Basics
Describes the use of collection views in iOS apps.
UICollectionView를 이용한 LINE iOS 대화방 리팩토링 - 1
들어가며 LINE의 대화방 화면은 사용자가 가장 많이 사용하는 화면 중 하나이며 새로운 기능이 계속 추가되고 있습니다. 그에 따라 코드가 점점 복잡해지면서 최근에 리팩토링을 진행했고, 그 과정에서 UICollectionView를 도입했습니다…