CLOSE SEARCH

컬렉션 뷰(UICollectionView) #1. iOS 앱의 UI 구현을 더욱 간편하고 강력하게!

지난 WWDC 2012에서 iOS를 위한 새로운 컨트롤이 하나 소개되었습니다. 컬렉션 뷰(Collection View)라고 하는 이 컨트롤은 iOS 6부터 사용할 수 있고, iOS에서 구현할 수 있는 UI의 영역이 획기적으로 확장될 수 있는 출발점이 될만한 놀라운 컨트롤이라고 생각합니다.

사실 컬렉션 뷰가 소개되기 이전에도 (실력만 있다면) 상상가능한 대부분의 UI를 구현하는 것은 가능했습니다. 하지만 개발자가 구현해야 되는 코드의 양은 어마어마 했습니다. 메모리 관리, 에니메이션, 속도 등 신경써야 할 것들이 많았고, 이들 중 어느 하나라도 잘못된 경우에는 앱이 죽어버리는 경우도 허다 했습니다. 이제 이러한 문제들을 한번에 해결해줄 컨트롤이 소개되었고, 그게 바로 컬렉션 뷰입니다.
Apple은 항상 새로운 컨트롤을 소개할 때, iOS 디바이스에 내장된 앱에 먼저 적용하는 버릇(?)이 있습니다. 지난 WWDC 2012에서 컬렉션 뷰를 소개하면서 아이패드에 내장된 시계 앱을 예로 들었습니다.

IMG_0046

 

iOS 6에 맞추어 새롭게 업데이트 된 시계 앱을 살펴보면, 세계시간이 그리드 형태로 화면에 표시되고 화면 방향이 바뀔때마다 애니메이션을 통해 UI가 자연스럽게 재구성되는 것을 볼 수 있습니다. 뿐만 아니라, 화면 아래쪽에 표시된 UI도 컬렉션 뷰를 통해 손쉽게 구현할 수 있다고 설명하고 있습니다. 컬렉션 뷰를 통해 선형 레이아웃, 원형 레이아웃, 다중 컬럼 레이아웃 등 상상가능한 모든 레이아웃을 쉽고 빠르게 개발할 수 있게 되었습니다.

 

New Classes

컬렉션 뷰와 관련해서 새롭게 추가된 클래스는 다음과 같습니다.
[list style=”star”]

  • UICollectionView : 컬렉션 뷰 클래스
  • UICollectionViewController : 컨트롤러 레벨에서 컬렉션 뷰를 관리할 수 있는 기능을 제공하는 클래스
  • UICollectionViewDataSource : 컬렉션 뷰에서 사용하는 데이터, 셀, Supplementary 뷰를 제공하는 프로토콜
  • UICollectionViewDelegate : 컬렉션 뷰에서 셀의 선택과 강조, 편집 메뉴 동작을 처리하는 프로토콜
  • UICollectionViewReusableView : 컬렉션 뷰에 표시되는 모든 뷰의 최상위 클래스
  • UICollectionViewCell : 컬렉션 뷰에 표시되는 셀 클래스. UICollectionViewReusableView를 상속합니다.
  • UICollectionViewLayout : 컬렉션 뷰가 셀을 화면에 표시할 때 사용하는 시각적 속성들을 정의하는 클래스
  • UICollectionViewLayoutAttributes : 레이아웃 속성 클래스
  • UICollectionViewUpdateItem : 컬렉션 뷰의 내용이 업데이트 될 때마다 레이아웃 객체가 전달받는 객체의 클래스. 이 객체는 시스템이 자동적으로 생성해주므로 직접 생성할 필요가 없습니다.
  • UICollectionViewFlowLayout : 그리드와 같은 선형 레이아웃을 표시하는데 사용되는 레이아웃 객체
  • UICollectionViewDelegateFlowLayout : 플로우 레이아웃 객체에서 사용하는 프로토콜

[/list]
상당히 많은 수의 클래스가 새롭게 추가되었지만 실제 구현 방식이 테이블 뷰의 방식과 상당히 유사해서 이해하기 쉬운 편입니다. 테이블 뷰에서 사용하던 “섹션”의 개념도 아주 유사한 의미로 사용되고, 각 아이템의 위치를 나타낼 때도 여전히 NSIndexPath를 사용합니다. 그리고 델리게이트 메소드의 이름과 역할도 매우 유사합니다.

[one_half]

UICollectionView

-numberOfSectionsInCollectionView:
-collectionView:numberOfItemsInSection:
-collectionView:cellForItemAtIndexPath:
-collectionView:didSelectItemAtIndexPath:
-collectionView:didDeselectItemAtIndexPath:

[/one_half]

[one_half_last]

UITableView

-numberOfSectionsInTableView:
-tableView:numberRowsInSection:
-tableView:cellForRowAtIndexPath:
-tableView:didSelectRowAtIndexPath:
-tableView:didDeselectRowAtIndexPath:

[/one_half_last]

위에 나열되지 않는 나머지 프로토콜들도 매우 유사한 패턴을 사용해서 구현되어 있습니다.

 

 

3 Main Things

컬렉션 뷰를 구성하는 주요한 3가지 요소는 Cell, Supplementary View, Decoration View 입니다.

셀(Cell)은 화면에 표시되는 하나의 아이템을 나타냅니다. 컬렉션 뷰에 표시되는 셀은 반드시 UICollectionViewCell 클래스의 인스턴스여야 합니다. 셀 내부에는 Background View, Selected Background View, Content View가 포함되어 있고, 화면에 표시되는 내용들은 Content View에 추가됩니다.

Supplementary View는 테이블 뷰에서 사용하는 Header나 Footer와 유사하지만, 테이블 뷰와 달리 미리 정의된 스타일이 없기 때문에 원하는 방식으로 얼마든지 표현할 수 있다.

Decoration View는 컬렉션 뷰의 배경을 구성하는데 사용됩니다. 셀이나 Supplementary View는 데이터 기반의 객체이지만 Decoration View는 레이아웃 기반입니다. 앞에서 설명한 아이패드의 시계 앱에서 화면 아래쪽에 표시된 셰게지도 역시 Decoration View입니다.

 

 

Reuse Mechanism

iOS의 부드러운 UI의 비밀 중 하나는 재사용 매커니즘(Reuse Mechanism)입니다. 테이블 뷰에서 상당히 많은 수의 셀을 부드럽게 스크롤 할 수 있는 것은 바로 재사용 매커니즘을 사용하기 때문입니다. 컬렉션 뷰 역시 재사용 매커니즘을 사용하기 때문에 셀의 수의 관계없이 아주 부드러운 UI를 구현할 수 있습니다.

재사용 매커니즘은 아주 직관적이고 간단한 방식으로 동작합니다.(물론 내부 구현은 아주 복잡할 것이라고 생각됩니다…)

  • 1. 컬렉션 뷰가 화면에 셀이나 뷰를 표시하기 전에 자신의 데이터 소스에 요청합니다.
  • 2. 데이터 소스는 컬렉션 뷰의 재사용 큐(Reuse Queue)에 사용가능한 셀이나 큐가 존재하는지 확인하고, 존재한다면 하나를 가져와서 사용하고(가져온 셀이나 뷰는 큐에서 삭제됩니다.), 존재하지 않는다면 새로운 셀이나 뷰를 생성합니다. (참고로 모든 컬렉션 뷰는 자신만의 재사용큐를 가지고 있습니다.)
  • 3. 셀이나 뷰를 원하는 방식으로 구성한 다음 리턴해 주면 컬렉션 뷰가 화면에 표시합니다.
  • 4. 사용자가 화면을 스크롤해서 화면 밖으로 이동된 셀이나 뷰는 바로 삭제되지 않고 재사용 큐에 추가됩니다.
  • 5. 1 ~ 4의 과정을 반복합니다.

위의 과정에서 “셀”이 아닌 “셀이나 뷰”로 표현한 것은 Cell, Supplementary View 모두 재사용 큐에 추가될 수 있기 때문입니다. 재사용 큐에 있는 항목들은 재사용 식별자(Reuse Identifier)를 통해 구별할 수 있습니다. 이 식별자는 컬렉션에 Cell이나 Supplementary View를 등록할 때 지정합니다.

컬렉션 뷰에 표시되는 셀이나 뷰들은 재사용 매커니즘을 사용하기 위해 반드시 UICollectionReusableView 클래스를 상속해야 합니다. 바꿔 말하면, UICollectionReusableView 클래스를 상속해서 얼마든지 커스터마이징이 가능합니다.

 

 

Layout Object

컬렉션 뷰는 테이블 뷰와 달리 화면에 표시되는 방식이 미리 정의되어 있지 않습니다. 대신 레이아웃 객체를 통해 화면에 표시되는 방식을 결정합니다. 레이아웃 객체는 오직 시각적인 부분만 담당하고, 실제 데이터에는 관여하지 않습니다. 이렇게 데이터와 UI가 분리되어 있기 때문에 UI 표시방식을 동적으로 변경할 수 있습니다.

레이아웃 객체에서 가장 중요한 포인트는 레이아웃 객체가 어떠한 뷰도 소유하지 않는다는 것입니다. 레이아웃 객체는 시각적인 속성들을 생성한 다음 컬렉션 뷰에 전달하는 역할만 하고, 이 속성들이 적용된 셀이나 뷰를 출력하는 것은 컬렉션 뷰의 역할입니다.

레이아웃 객체를 통해 크기, 위치, 투명도, 3D 변환 등 다양한 시각적 속성을 지정할 수 있습니다.

 

 

Animation

컬렉션 뷰는 셀이 추가되거나, 삭제되거나, 다른 위치로 이동될 때 기본적인 에니메이션을 통해 사용자에게 좀 더 나은 시각적 피드백을 제공합니다. 다만, 두개 이상의 셀을 동시에 추가, 삭제, 이동할 때는 배치 업데이트를 통해서 컬렉션 뷰가 전체 에니메이션을 통합할 수 있도록 해준 경우에만 에니메이션을 보여줍니다.

Filed under: iOS