본문 바로가기
Swift/UIKit

버튼을 통해 IndexPath 전달하기

by songmoro 2025. 8. 18.

 

테이블뷰 안의 컬렉션뷰, 그리고 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를 기반으로 좋아요를 하는 등의 버튼 단위 액션이 필요한 경우 훨씬 직관적인 해결책이 될 것이라고 생각한다.