[swift] RxDataSources를 사용한 컬렉션 뷰의 드래그 앤 드롭 처리 방법
이번 블로그 포스트에서는 RxDataSources를 사용하여 iOS 앱에서 컬렉션 뷰의 드래그 앤 드롭 기능을 구현하는 방법에 대해 알아보겠습니다.
목차
RxDataSources란?
RxDataSources는 RxSwift와 결합되어 데이터 소스를 관리하는 편리한 도구입니다. 이를 통해 리액티브한 방식으로 컬렉션 뷰나 테이블 뷰의 데이터를 관리할 수 있습니다.
컬렉션 뷰 설정
드래그 앤 드롭을 구현하기 전에 먼저 컬렉션 뷰를 설정해야 합니다.
// 컬렉션 뷰 설정
func setupCollectionView() {
collectionView.dragInteractionEnabled = true
collectionView.dragDelegate = self
collectionView.dropDelegate = self
}
드래그 앤 드롭을 활성화하려면 dragInteractionEnabled
속성을 true
로 설정해야 합니다. 그리고 dragDelegate
와 dropDelegate
를 설정하여 드래그 앤 드롭 이벤트를 처리할 수 있습니다.
드래그 앤 드롭 구현
RxDataSources를 사용하여 컬렉션 뷰에서 드래그 앤 드롭을 구현하는 방법은 다음과 같습니다.
- Drag and Drop을 위한 Gesture Recognizer 추가
collectionView.rx.dragDelegate()
.disposed(by: disposeBag)
collectionView.rx.dropDelegate()
.disposed(by: disposeBag)
- 드래그 시작 시 데이터 소스를 업데이트하는 방법 정의
func dragItems(at indexPath: IndexPath) -> [UIDragItem] {
guard let item = collectionView.dataSource?[indexPath.item] else { return [] }
let itemProvider = NSItemProvider(object: item)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
collectionView.rx.dragItemsForBeginning(at: { [weak self] indexPath in
return self?.dragItems(at: indexPath) ?? []
})
.asDriver(onErrorJustReturn: [])
.drive(onNext: { [weak self] items in
self?.draggedItems = items
})
.disposed(by: disposeBag)
- 드롭이 허용되는 경우 데이터 소스를 업데이트하는 방법 정의
collectionView.rx.dropDelegate().performDropWithCoordinator = { [weak self] coordinator in
guard let self = self else { return }
let destinationIndexPath: IndexPath
if let indexPath = coordinator.destinationIndexPath {
destinationIndexPath = indexPath
} else {
let section = self.collectionView.numberOfSections - 1
let row = self.collectionView.numberOfItems(inSection: section)
destinationIndexPath = IndexPath(row: row, section: section)
}
coordinator.session.loadObjects(ofClass: YourDataType.self) { items in
let item = items.first as? YourDataType
// 드롭된 아이템에 대한 처리
// 데이터 소스 업데이트 등
}
}
- 데이터 소스에 대한 변경 사항을 컬렉션 뷰에 반영하는 방법
let dataSource = RxCollectionViewSectionedReloadDataSource<YourSectionModelType>(
configureCell: { dataSource, collectionView, indexPath, item in
// 셀 구성
},
configureSupplementaryView: { dataSource, collectionView, kind, indexPath in
// 보조 뷰 구성
})
// 데이터 소스 변경 반영
viewModel.items
.bind(to: collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
결론
RxDataSources와 함께 사용하면 쉽게 컬렉션 뷰의 드래그 앤 드롭을 구현할 수 있습니다. 드래그와 드롭을 위한 Gesture Recognizer를 추가하고, 드래그/드롭 이벤트에 대한 처리 방식을 정의한 후, 데이터 소스에 대한 변경을 컬렉션 뷰에 반영하면 됩니다. 이를 통해 iOS 앱에서 경량하고 반응적인 드래그 앤 드롭 기능을 구현할 수 있습니다.