10/09
- [x] 평점 Realm Write 고도화
- [x] 맵 상세에서 데이터를 변경하고 pop으로 나왔을 떄 화면의 보여지는 셀에만 데이터를 반영
- 네트워크 통신으로 받아온 값을 Realm에 저장된 데이터와 비교하여 값을 필터링하는 작업이 필요했다.
- 내가 짜고 싶었던 로직은 네트워크 통신 시 받은 데이터 배열 모두를 반복문을 통해 모두 필터링하여 값을 방출하는 로직이 아니라**, 통신 이후 셀에 보여지는 데이터만 필터링 처리하고 싶었다. 즉, 모든 셀을 체크하지 않고, 화면에 노출된 셀만 필터링하는 기능이라고 볼 수 있다.**
- 두 가지 고려사항이 필요했다.
- 맵 상세에서 데이터를 변경한 후 pop 했을 때 && 다른 탭에 데이터를 변경하고 진입 했을 때
- 내 위치 버튼 && 맵 위치를 변경한 후 카테고리 버튼 or 리프레쉬 버튼을 선택했을 때 통신을 통해 셀 배열 데이터를 지우고 다시 그릴 때
첫 번째는 CollectionView.rx.willDisplayCell를 활용했다
input.viewWillAppearEvent
.withLatestFrom(input.willDisplayCell)
.withUnretained(self)
.bind(onNext: { owner, indexPath in
print("willDisplayCell", indexPath)
owner.searchLocationUseCase.updateStoreCellObservable(index: indexPath.row, storeList: owner.storeList)
})
.disposed(by: disposeBag)
- input으로 들어오는 viewWillAppear 이벤트를 트리거로 활용해서 withLatestFrom으로 그려질 셀의 indexPath를 넘겨주는
willDisplayCell
을 받아왔다.
- 그리고
searchLocationUseCase.updateStoreCellObservable
함수를 실행시켜 현재 보여지는 셀의 데이터를 업데이트 시키고 셀을 다시 그렸다.
func updateStoreCellObservable(index: Int, storeList: [StoreVO]) {
realmRepository.updateStoreCellObservable(index: index, storeList: storeList)
.subscribe(with: self, onSuccess: { owner, storeVO in
owner.updateStoreVO.onNext(storeVO)
}, onFailure: { owner, error in
owner.errorSubject.onNext(error)
})
.disposed(by: disposebag)
}
- UseCase의
updateStoreCellObservable
메서드는 업데이트를 성공했을 때 updateStoreVO.onNext(storeVO)
을 통해 업데이트된 storeVO
를 onNext 시킨다.
self.searchLocationUseCase.updateStoreVO
.withLatestFrom(input.willDisplayCell) { storeVO, willDisplayCell in
return (storeVO, willDisplayCell)
}
.withUnretained(self)
.bind(onNext: { owner, visibleStore in
let (storeVO, willDisplayCell) = visibleStore
let visibleStore = owner.storeList[willDisplayCell.row]
if owner.shouldUpdateStore(store: storeVO, visibleStore: visibleStore) {
owner.storeList[willDisplayCell.row] = storeVO
output.storeList.accept(owner.storeList)
}
})
.disposed(by: disposeBag)
transformCollectionViewDataSource(input: input, output: output)
return output
}
- 다시 viewModel에서는 위에서 onNext한
updateStoreVO
를 구독하여 변경된 storeVO를 viewModel에 전역변수로 지정해놓은 storeList에서 찾은 뒤 변경해주고 output.storeList에 accept 해준다.
- output.storeList를 combineLastest로 구독하고 있는
CollectionViewDataSource
는 storeList의 값이 변경됨에 따라 셀을 다시 그리게 된다.
두 번째는 rx.items에서 필터링을 하는 방법을 사용했다.
output.storeCollectionViewDataSource
.bind(to: locationView.storeCollectionView.rx.items(cellIdentifier: "StoreCollectionViewCell", cellType: StoreCollectionViewCell.self)) { [weak self]
index, item, cell in
if let updatedItem = self?.viewModel.updateStoreCell(item) {
cell.configureCell(item: updatedItem)
}
}
.disposed(by: disposeBag)
- 첫 번째 방법만 구현한다면 셀이 정상적으로 업데이트되긴 한다. 하지만, 내 위치 버튼 혹은 다시 찾기 버튼을 진행하게되면 네트워크 통신을 다시 하게되어 원래 배열에 담긴 데이터가 없어지고 새로운 데이터가 들어와서 셀을 그리게 되는데 그렇게 되면 셀의 데이터가 필터링 되지 않은 네트워크통신에서 넘어온 데이터가 보여지게 된다.
rx.items
에서 item을 필터링해주고 해당 데이터를 바인딩했다.
Observable.zip(locationView.storeCollectionView.rx.modelSelected(StoreVO.self), locationView.storeCollectionView.rx.itemSelected)
.withUnretained(self)
.bind(onNext: { [weak self] data in
if let updatedItem = self?.viewModel.updateStoreCell(data.1.0) {