cchanmi
[iOS] UIKit+Combine 환경에서 CollectionView Cell 바인딩 문제 해결 본문
ViewModel로부터 관찰한 데이터를 sink 클로저 안에서 CollectionView에 바인딩을 해야 했습니다.
output.totalHasMyPlanResult
.receive(on: DispatchQueue.main)
.sink { [weak self] response in
print("collectionView에 바인딩 될 데이터: ", response)
}
.store(in: &cancelBag)
MVVM 원칙에 따라 View가 Data를 알 필요가 없었기 때문에, 해당 데이터를 전역으로 추가하여 외부 CollectionViewDatasource 메서드에서 바인딩 할 수 없었던 상황이었습니다.
생각나는 방안으로는 2가지가 있었습니다.
1) CollectionViewDiffableDatasource를 사용하기
2) 직접 CollectionViewDatasource를 구현하기
func setUpDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView, cellProvider: { (collectionView, indexPath, card) -> UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
return cell
})
}
1번 방법을 사용하면 cellProvider 클로저를 통해 collectionView의 cell에 접근할 수 있었지만, 현재 뷰에서는 데이터의 변동이 없고, 다이나믹한 애니메이션 처리가 필요하지 않았기 때문에 DiffableDatasource를 도입할 필요는 없다고 생각했습니다.
그런 이유로 2번 방법으로 택했고, 직접 CollectionViewDatasource 구현하여 바인딩을 해 주어 해결했습니다.
전역으로 해당 CollectionViewDatasource를 선언만 해 두고, sink 클로저 내에서 해당 CollectionView에 맞는 데이터를 초기화 시에 주입해 주었습니다.
// 전역으로 선언
private var mySmeemDataSource: MySmeemCollectionViewDataSource!
output.totalHasMyPlanResult
.receive(on: DispatchQueue.main)
.sink { [weak self] response in
self?.mySmeemDataSource = MySmeemCollectionViewDataSource(numberItems: response.mySummaryNumber,
textItems: response.mySumamryText)
self?.mySmeemCollectionView.dataSource = self?.mySmeemDataSource
self?.mySmeemCollectionView.reloadData()
}
.store(in: &cancelBag)
아쉬운 점
1. Datasource가 데이터를 알게 되는 상황
final class MySmeemCollectionViewDataSource: NSObject, UICollectionViewDataSource {
private let numberItems: [Int]
private let textItems: [String]
init(numberItems: [Int], textItems: [String]) {
self.numberItems = numberItems
self.textItems = textItems
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(cellType: MySmeemCollectionViewCell.self, indexPath: indexPath)
cell.setNumberData(number: self.numberItems[indexPath.item])
cell.setTextData(text: self.textItems[indexPath.item])
return cell
}
}
Datasource 초기화 시에 데이터를 주입해 준 이후 바인딩은 collectionView 메서드에서 일어나기 때문에, 전역으로 데이터를 가지고 있어야 하는 상황이 발생했습니다.
MVVM 원칙을 따르기 위해 해당 방안을 도입한 것이었는데, 결국에은 ViewController가 아닌 Datasource가 데이터의 책임에 갖게 되어서 아쉬움이 남았습니다.
꼭 다이나믹한 데이터 바인딩이나 애니메이션 처리가 중요한 상황이 아니더라도, MVVM 원칙을 지키기 위해 DiffableDatasource를 도입하는 것도 하나의 이유가 될 수 있겠다는 생각이 들었습니다.
'iOS' 카테고리의 다른 글
[iOS] Github Action 도입기 - build & test (2) | 2024.11.30 |
---|---|
[RxSwift] RxSwift의 메모리 누수에 대해서 (1) | 2024.09.08 |
[iOS] RxSwift 정리 (1) | 2024.09.04 |
[iOS] CollectionView Cell 재사용에 따른 중복 binding 이슈 해결 (0) | 2024.08.31 |
[iOS] TextView Responder 권한이 남아 있어 Keyboard 감지 Notification이 중복 호출 되는 이슈 해결 (0) | 2024.08.04 |