테이블뷰 안의 컬렉션뷰, 그리고 IndexPath
개발을 하다 보면 테이블 뷰 안에 또 다른 뷰가 들어가는 경우가 왕왕 있다.
대표적인 예시가 테이블 뷰 셀 안에 컬렉션 뷰를 넣는 것인데, 가로 스크롤 리스트 UI를 위해 사용했다.
이 경우에 생긴 문제가 하나 있는데, 컬렉션 뷰 셀을 선택했을 때, 원래 어떤 테이블 뷰 섹션/셀에 속하는지를 알아내기 어렵다는 점이다
왜 IndexPath가 꼬일까?
테이블 뷰는 IndexPath(row:section:)를 가지고 있고, 컬렉션 뷰도 IndexPath(item:section:)를 가지고 있다.
즉, 테이블 뷰 기준의 IndexPath, 컬렉션 뷰 기준의 IndexPath
이렇게 두 개의 계층이 겹치면서 “내가 선택한 셀이 테이블 뷰 몇 번째 섹션에 속하는지”를 알기가 까다로워졌다.
WithIndexPathButton
이 문제를 해결하기 위해 만든 커스텀 버튼.
class WithIndexPathButton: BaseButton {
var indexPath = IndexPath()
init(indexPath: IndexPath = IndexPath()) {
super.init(frame: .zero)
self.indexPath = indexPath
}
func update(_ indexPath: IndexPath) {
self.indexPath = indexPath
}
}
버튼 자체가 자신의 IndexPath 정보를 기억하게 만들고, 이를 NotificationCenter/Delegate/Selector를 통해 전달하게 만드는 것
주요 아이디어
- indexPath 프로퍼티를 버튼 안에 저장
- 셀을 업데이트할 때마다 버튼의 update(_:) 메서드를 호출
- 버튼 액션에서 sender.indexPath를 그대로 활용
사용 예시
컬렉션 뷰 셀 안에 이 버튼을 넣고, 테이블 뷰의 cellForRowAt 또는 컬렉션 뷰의 cellForItemAt에서 IndexPath를 주입
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
cell.actionButton.addTarget(self, action: #selector(didTapItemButton(_:)), for: .touchUpInside)
// case 1
cell.actionButton.update(IndexPath(row: indexPath.row, section: collectionView.tag))
// case 2
cell.actionButton.update(indexPath)
return cell
}
@objc private func didTapItemButton(_ sender: WithIndexPathButton) {
print("선택된 테이블 섹션: \(sender.indexPath.section), 컬렉션 아이템: \(sender.indexPath.row)")
}
여기서 collectionView.tag를 활용하면 상위 테이블 뷰 섹션 정보까지 같이 담을 수 있다.
마무리
테이블 뷰 안의 컬렉션 뷰처럼 계층 구조가 깊어지면 IndexPath 전달이 골칫거리가 되며, 이를 해결하기 위한 여러 방법이 있다.
이를 단순화하기 위해 IndexPath를 보유한 버튼을 만들어 사용했으며, 물론 이 방식은 버튼 액션 기반으로 셀 전체를 선택하는 방식에서는 didSelectItemAt을 쓰는 게 더 자연스러울 수 있다
하지만, 아이템의 id를 기반으로 좋아요를 하는 등의 버튼 단위 액션이 필요한 경우 훨씬 직관적인 해결책이 될 것이라고 생각한다.
'Swift > UIKit' 카테고리의 다른 글
| UIKit: UITextView (1) | 2025.08.30 |
|---|---|
| UIControl 이벤트를 Combine 퍼블리셔로 만들기 (0) | 2025.08.20 |
| UIKit: TableView, CollectionView register, dequeue 셀 식별자 (2) | 2025.07.31 |
| UIKit: 테이블 뷰 셀 내부에 원형 뷰 만드는 방법 (3) | 2025.07.28 |
| UIKit: Layout Cycle (0) | 2025.07.27 |