반응형

서론
UITableView나 UICollectionView와 같은 컴포넌트를 RxCocoa로 바인딩하여 사용하다 보면, 셀을 클릭했을 때 이벤트가 트리거되지 않는 경우가 있습니다. 예를 들어, tableView.rx.itemSelected를 사용하여 셀 클릭 이벤트를 처리하려고 할 때, 특정 상황에서 이 이벤트가 호출되지 않는 현상이 발생할 수 있습니다. 특히, UITableView의 델리게이트 메서드를 직접 구현하면서 Rx와 중복으로 설정하게 되면 이러한 문제가 발생할 가능성이 높아집니다.
원인
RxCocoa는 내부적으로 UITableView의 델리게이트를 설정하여 각종 이벤트를 Rx 스트림으로 제공하는데, 개발자가 직접 델리게이트를 설정하게 되면 Rx가 설정한 델리게이트가 무효화되면서 예상치 못한 동작이 발생할 수 있습니다. 이는 RxCocoa가 델리게이트 메서드를 통해 이벤트를 수집하고 있는데, 직접 델리게이트를 오버라이드하면 Rx의 이벤트 흐름이 끊겨버리기 때문입니다.
해결방법
Rx에서 제공하는 setDelegate 사용하기
- RxCocoa는 기본적으로 setDelegate 메서드를 제공하여 기존 델리게이트와 Rx를 함께 사용할 수 있는 방법을 제공합니다. 이 방법을 통해 Rx와 델리게이트가 충돌하지 않도록 설정할 수 있습니다.
// UITableViewDelegate를 커스텀으로 설정해야 할 경우
tableView.rx.setDelegate(self)
.disposed(by: disposeBag)
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// 셀의 크기를 조정하는 로직
return 100.0
}
}
tableView.rx.itemSelected
.subscribe(onNext: { [weak self] indexPath in
// 셀 클릭 이벤트 처리
self?.handleCellSelection(at: indexPath)
})
.disposed(by: disposeBag)
RxCocoa Extension 활용하기
- 직접 구현이 꼭 필요한 델리게이트 메서드가 있을 경우, RxCocoa의 확장을 통해 델리게이트 메서드를 Rx 스트림으로 변환하여 사용할 수 있습니다. 이를 통해 델리게이트와 Rx 간의 충돌을 최소화할 수 있습니다.
extension Reactive where Base: UITableView {
var willDisplayCell: ControlEvent<(cell: UITableViewCell, indexPath: IndexPath)> {
let source = delegate.methodInvoked(#selector(UITableViewDelegate.tableView(_:willDisplay:forRowAt:)))
.map { a in
return (cell: a[1] as! UITableViewCell, indexPath: a[2] as! IndexPath)
}
return ControlEvent(events: source)
}
}
tableView.rx.willDisplayCell
.subscribe(onNext: { cell, indexPath in
// 셀 표시 이벤트 처리
})
.disposed(by: disposeBag)
반응형
'iOS > RxSwift' 카테고리의 다른 글
[RxSwift] withUnretained 를 대체하는 subscribe(with:onNext:) (0) | 2024.10.28 |
---|---|
[RxSwift] Single + Extension을 통해 로깅 시스템 구현 (0) | 2024.10.20 |
[RxSwift] PrimitiveSequenceType (0) | 2024.09.30 |
[RxSwift] Merge와 concat (0) | 2024.09.19 |
[RxSwift] 재사용으로 인해, 테이블뷰 셀안에 버튼이 반응하지 않을때 (0) | 2024.07.10 |