Collection view를 활용하여, 아래와 같은 reordering을 구현하는 방법을 한번 알아보겠습니다!(with ListConfiguration)
먼저 reordering과 관련된 WWDC 20의 Advances in diffable data sources를 정리하고 구현해보도록 하겠습니다.
Diffable datasource의 가장 큰 장점은 유니크한 item identifier를 통하여 Collection view의 데이터를 모델링할 수 있다는 것입니다.
이러한 유니크한 item identifier를 통하여, 프레임워크가 자체적으로 reordering된 변화점을 알아서 확인하지만, 이것만으로는 충분하지 않습니다. 우리의 앱은 유저가 발생시킨 reordering 작업을 알아차려야지, 새로운 reordering 순서를 backing store에 저장할 수 있습니다.
이러한 과정을 위해서는 reorderingHandlers라는 프로퍼티를 활용해야됩니다.
ReorderingHandlers는 총 3개의 optional한 클로져를 가지고 있습니다. canReorderItem, willReorder 그리고 didReorder입니다.
Reordering을 가능하게 하기위해서는 canReorderItem 클로져를 먼저 적용해야됩니다. 해당 클로져는 유저가 reordering 작업을 시작할 때 호출이 됩니다. 만약 해당 클로져가 true를 던지면, reordering 작업은 시작이됩니다.
만약 reodering 작업이 완료가 된다면, didReorder 클로져가 호출이 되어 앱이 새로운 ordering 상태를 앱의 source of truth에 적용할 수 있도록 합니다. 즉, reordering을 하려면 canReorderItem, didReorder 클로져 둘 다를 무조건 활용해야됩니다.
didReorder 클로져는 NSDiffableDataSourceTransaction라는 새로운 타입을 closure의 파라미터로 전달합니다.
NSDiffableDataSourceTransaction은 위와 같이 구성이되어있습니다.
intialSnapshot은 update가 적용되기 전의 Diffabledatasource의 상태를 던져줍니다. finalSasnpShot은 update가 적용된 후의 상태를 던져줍니다. 또한, Swift의 standard 라이브러리인 CollectionDifference를 던지는 difference 프로퍼티도 존재합니다. 우리는 만약 Array로 구성된 데이터 타입을 가지고 있다면 위와 같은 프로퍼티를 활용하면 되겠죠.
(이 부분은 활용을 해보면서 조금 더 알아보겠습니다.)
마지막으로 reordering 작업에 연관된 모든 섹션들의 디테일을 담고 있는 section transactions list를 던져주는 sectionTransactions 프로퍼티도 존재합니다.
위의 코드에서 backing store는 하나의 섹션을 가지고 있는 콜렉션의 source of truth를 가지고 있는 아이템들의 배열입니다. transaction에서 제공하는 CollectionDifference를 통하여 새로운 backing store를 생성할 수 있고, source of truth를 바로 업데이트할 수 있습니다.
사실 WWDC 내용만으로는 무슨 내용인 지 감이 오지는 않습니다. 따라서 공식문서를 참고하여 직접 구현을 해보며 이해 안되는 부분을 채워보도록 하겠습니다.
먼저 canReorderItem 과 didReorder 두 클로져를 활용해됩니다.
canReorderItem은 어떠한 item을 reorder할 지를 설정할 수 있습니다.
저는 모든 item들을 다 reorder할 수 있게 구현하고 싶기에 아래와 같이 구현해보겠습니다.
// dataSource = UICollectionViewDiffableDataSource<Section, Item>
datasource?.reorderingHandlers.canReorderItem = { item in return true }
그리고 이렇게 변경된 order를 통하여 실제로 데이터도 변경을 해야됩니다. 해당 과정은 didReorder 클로져를 통하여 구현할 수 있습니다.
만약 section이 한 개라면 위의 WWDC 예와 같이 구현을 하면 됩니다. 사실 저의 프로젝트에서는 하나의 section만을 가지고 있기에 아래와 같이 구현을 해보겠습니다.
datasource?.reorderingHandlers.didReorder = { [weak self] transaction in
if let updatedBackingStore = self?.backingStore.applying(transaction.difference) {
self?.backingStore = updatedBackingStore
}
}
위와 같이 backing store를 didReorder 클로져를 통해서 변경을 해주어야지, 순서의 변화가 source of truth에도 제대로 적용이됩니다.
'iOS' 카테고리의 다른 글
[iOS] TabbarController의 presentingViewController(feat.currentContext) (0) | 2024.03.26 |
---|---|
[iOS] JSONEncoding과 URLEncoding의 차이점(Alamofire/Moya) (1) | 2024.03.05 |
[iOS] Core Location Unit Test하기(feat. WWDC18) (0) | 2023.07.23 |
[iOS] 공식문서로 보는 Core Location (0) | 2023.07.16 |
[iOS] delegate는 항상 weak var로 선언해야 될까? (0) | 2023.06.12 |