본문 바로가기
IOS🍎/WWDC

[WWDC 2020] Advances in diffable data sources

by Jouureee 2022. 5. 12.

2021 DiffableDataSource의 개선 사항을 보기 전, 관련 영상이 2020년도꺼도 있길래 먼저 보고 가자는 생각에 정리하게 되었다.

https://developer.apple.com/videos/play/wwdc2020/10045

 

Advances in diffable data sources - WWDC20 - Videos - Apple Developer

Diffable data sources dramatically simplify the work involved in managing and updating collection and table views to create dynamic and...

developer.apple.com

 

iOS 14부터 Outline Style UI가 추가되었습니다. UICollectionViewListCell이라는 새로운 형태의 cell이 추가되었는데,

리스트 형태로 제공되는 cell 

그러면 tableviewCell 아닌가 ? 왜 tableviewCell를 두고 새롭게 listCell이 생성된 것인가 하고 예시를 보니

expandable하네요 !!

사실 collectionview로나 tableview로나 무엇을 적용하는지는 view의 특징을 고려해서 선택될뿐 정해진 바는 없다 생각합니다. apple document에 collectionView는 nested view를 다룰때 collectionView가 더 적합하다 생각하여 UICollectionViewListCell 이 새롭게 생겨난 것이라고 봅니다.

expandable view를 만들기 위한 다양한 방법이 있지만 UICollectionViewListCell로 구현하니 view를 reload하지 않고 재사용한다는 점에서 가장 깔끔한 방식이라는 생각이 들었습니다. 

 

Advances in diffable data sources 영상에서는 이를 위한 다양한 API를 추가했다고 소개했는데요 서론이 넘 길었습니다. 

영상 속 내용을 정리해보겠습니다.

 

iOS 13에서 소개된 diffable data source는 snapshot이라는 개념을 사용하여 UI state를 관리했습니다. snapshot은 section, item identifier를 사용하여 UI state를 캡슐화합니다. UICollectionView를 업데이트 할 때, 새 snapshot을 생성하고 datasource에 apply() 했었습니다. 만약 diffable data source에 대해 처음 접한다면, 아래 WWDC 세션을 보는 것을 권유 드립니다.

https://developer.apple.com/videos/play/wwdc2021/10252/

 

Make blazing fast lists and collection views - WWDC21 - Videos - Apple Developer

Build consistently smooth scrolling list and collection views: Explore the lifecycle of a cell and learn how to apply that knowledge to...

developer.apple.com

 

iOS 14에선 이 diffableDataSource에 기반하여 2가지 feature를 더 소개하려 합니다.  바로 Section Snapshot과 first Class Reordering Support입니다. 

 

Section Snapshot

Section snapshot은 이름에서 알 수 있듯이, single section을 위한 data를 캡슐화합니다. 이러한 개선에는 두 가지 이유가 있습니다. 
첫째, data source를 section 크기의 청크로 구성할 수 있도록 합니다.
둘째, iOS 14 전체에서 볼 수 있는 common visual design인 outline style UI rendering을 지원하는데 필요로 되는 계층적 data 모델링을 허용하기 위해서 입니다.

다시 emoji explore로 가서 어떻게 section snapshot이 데모 화면을 구성하고 있는지 살펴봅시다.

첫번째 section은 이 content를 완전히 모델링하기 위해 single section snapshot을 사용했습니다.

두번째는 section은 expandable하고 collaspsible(확장, 축소가 가능한) outline-style section을 위해 계층적 data model을 사용했습니다. 

마지막 list section은 third section snapshot입니다. 

 

이 3개 section snapshot으로 부터 diffableDataSource를 구성했습니다. 각각의 section은 single section content를 나타냅니다. 
iOS 13에선 section과 item Identifier를 포함하는 snapshot type이었습니다.

 

iOS 14에서는 item identifier를 파라미터화하는 section snapshot을 새롭게 소개합니다. 여기에는 section identifier가 없습니다. 
우리의 section snapshot에 content를 더하기 위해 append 메서드를 사용해봅시다. 

append의 parent parameter는 optional 입니다. parent에 값이 있다면 계층적 데이터를 모델링하는 데 필요한 section snapshot에서 상위-하위 관계를 생성할 수 있습니다.

 

 

Section snapshot을 위한 두가지 메서드가 추가 되었습니다.
snapshot() 함수는 특정 section의 content를 대표하기 위한 snapshot을 반환합니다. 

 

snapshot을 생성해 snapshot에 section을 추가하고 apply()합니다. 
그리고 section의 item을 각각 popluate하여 section snapshot에 넣고 apply()합니다.

 

데모 예시의 두번째 section를 통해 section snapshot으로 계층적 data model을 만드는 방법을 살펴봅시다.
Section snapshot에 section을 append 해주고 있습니다.
그리고 부모 Food section에 item을 넣어주고 있습니다. 이를 통해 계층적 Data를 만들었습니다. 

또한 계층적 데이터의 일부를 가지고 부모 section으로 child snapshot을 추론할 수 있습니다.

 

다음으로 expansion state에 대해 살펴봅시다. 

expansion state는 section snapshot state의 일부분으로 관리됩니다. 

snapshot을 쿼리하여 항목이 확장 또는 축소되었는지 확인할 수도 있습니다.

section snapshot 의 expasion state를 변경하면 실제로 이를 Diffable data source에 적용할 때까지 적용되지 않습니다.

사용자가 새로운 Cell Outline Disclosure Accessory로 구성된 ouline style의 UI와 상호 작용할 때 프레임워크는 자동으로 section snapshot을 새로운 expasion state로 업데이트하고 해당 section snapshot을 data source에 적용합니다. 

 

sectionSnapshotHandler를 사용하여 diffable data source의 상태를 알아차릴 수 있습니다. struct로 제네릭 타입이며 5가지 handler를 옵셔널로 가집니다. 

shouldCollaseItem handler는 outline의 collapsing(축소)을 피하기 위해 특정 parent에게 false를 리턴하는 handler입니다. 

또한 expensive content의 lazy loading을 지원하기 위해 snapshotForExpandingParent를 제공합니다. 이것은 initial section snapshot에서 값비싼 많은 양의 content가 로드되는 것을 최소화하기 위해 유용합니다. 

 

Reordering Support

Diffable Data Source의 개선 중 하나는 collectionview의 data를 unique item identifier로 모델링하는 기능입니다. unique item identifier를 사용하면 프레임워크가 사용자 상호 작용을 기반으로 애플리케이션을 대신하여 ordering 변경 사항을 자동으로 commit할 수 있습니다. 하지만 이것만으로는 충분하지 않습니다. User-initiated reordering 상호작용이 발생했음을 알려야 truth의 final source인 앱의 백업 저장소에 새로운 visual order를 유지할 수 있습니다. 따라서 reordering을 지원하기 위해 Diffable Data Source에는 이제 reorderingHandlers라는 새 속성을 가집니다.

canReorderItem : 사용자가 reordering interaction을 시도할때 true를 반환합니다.
didReorder : 사용자가 reordering interaction을 다했을때 호출되는데, 앱이 새 ordering state에 commit하는 것을 허용합니다.
reordering을 가능하게 하기 위해선 canReorderItem와 didReorder 모두 제공되어야 합니다. didReorder는 NSDiffableDataSourceTransaction을 전달합니다.

 

트랜잭션은 Diffable DataSource에 대해 수행되는 업데이트에 대해 추론하는 데 필요한 모든 정보를 제공합니다. 먼저 NSDiffableDataSourceTransaction를 살펴봅시다. 이 타입은 4개의 information을 제공합니다. 우선 initialSnapshot을 가집니다. 이것은 Diffable DataSource의 update가 apply되기 전의 상태입니다. finalSnapshot은 Diffable DataSource의 update가 apply된 후의 상태입니다. 

이 Snapshot의 item identifier를 직접 사용하여 앱의 truth source에 commit해야 하는 새 ordering를 결정할 수 있습니다. 추가로 CollectionDifference도 제공됩니다. 앱에 truth source에 array와 같은 데이터 타입을 가지고 있다면 CollectionDifference를 직접적으로 apply 할 수도 있습니다. 마지막으로 reordering update안에 포함된 모든 section에 대해 각 section의 detail을 제공해주는 sectionTransaction이 있습니다. 

먼저 이 sectionTransaction이 적용된 sectionIdentifier를 검사할 수 있습니다. 또한 이 section 업데이트에 CollectionDifference와 함께 initial 및 final section snapshot이 있습니다. 
그럼 예제를 확인해봅시다. 

backingStore는 단일 section collectionview에 대한 truth source를 제공하는 item 배열입니다.

트랜잭션과 함께 제공된 Swift 표준 라이브러리 CollectionDifference를 사용하여 새로운 백업 저장소를 만들고 최종적인 소스(source of truth)를 직접 업데이트합니다.

 

아직 트랜잭션에 대해서는 잘 이해가 가지 않네요 .. 사용 예시를 조금 읽고 와서 덧붙여 이해한 바를 정리하길 기대하며 .. 끝 !!

댓글