Delegation 패턴을 이용하여 Cell내부의 버튼 이벤트 처리하기

1 답변 글타래를 보이고 있습니다
  • 글쓴이
    • 쥬트
      참가자
      • 글작성 : 9
      • 답글작성 : 8

      앱잼동안 구현했던 부분중에 테이블 뷰 셀 안에 버튼을 넣어서 버튼 액션을 다르게 처리해야 했었다.

      테이블 뷰 셀 예시

      옆에 필터 같은 버튼을 누르면 테이블뷰 셀에 표시가 되었고 해당 제품의 성분정보가 테이블 뷰 상단에 보였다. 보통 많은 자료에서 이러한 문제를 해결 할때 버튼의 Target-Action을 설정하여 이벤트 처리를 하는데 Delegation 패턴을 사용하여 해결하는 방법에 대해 알아 보도록 하겠다.

      Delegation패턴이란?

      사전 해석에 따르면 ‘위임자’ 라고 한다. 즉, 하나의 객체가 다른 객체를 대신해 동작 또는 조정할 수 있는 기능을 제공한다. 주로 프레임워크 객체가 위임을 요청하고 커스텀 컨트롤러 객체가 위임을 받아 특정 이벤트에 대한기능을 구현한다.

      TableView의 예를들면 테이블뷰의 동작을 커스텀할 때 UITableViewDelegate 프로토콜을 상속받아 상세동작을 구현할 수 있다.

      패턴 적용

      Delegation 패턴을 적용하여 버튼에 대한 액션을 구현해 보겠다.

      먼저, 위임을 요청하는 객체는 테이블뷰 Cell의 커스텀 객체이다. 테이블뷰 구현할 때 커스텀 Cell 클래스를 작성하였을 것이다. 그리고 셀 내부를 구성하는 프로퍼티들이 있고 그 안에 우리가 이벤트를 설정할 버튼이 존재할 것이다.

      하지만 어떤 동작을 위임할지 위임받는 객체는 알 수가 없기 때문에 위임을 요청 할 메소드를 프로토콜로서 정의한다.

      protocol ComponentProductCellDelegate {
          func selectedInfoBtn(index: Int)
      }
      

      그리고 커스텀 테이블뷰 Cell의 프로퍼티로 해당 프로토콜 객체를 생성하고 선택한 셀의 index를 통해 제품 정보를 서버에서 불러와야 하기 때문에 index프로퍼티를 생성한다. 그 다음 우리가 처리하야할 이벤트 처리에 관한 것을 이 객체가 처리하도록 하고 프로퍼티의 index 값을 넘긴다.

      class ComponentProductCell: UITableViewCell {
          …
          @IBOutlet var selectInfoBtn: UIButton!
          var index: Int = 0
          var delegate: ComponentProductCellDelegate?
      
          …
          @IBAction func selectedInfoBtn(_ sender: Any) {
              self.delegate?.selectedInfoBtn(index: index)
          }
      }
      

      이제 뷰컨트롤러 에서 위임 받을일 만 남았다.테이블뷰가 존재하는 커스텀 뷰 컨트롤러에서는 테이블뷰의 DataSouce를 상속받아 각 Cell을 구성하게 된다. 이 때 앞서 구현한 커스템 셀로 구성을 하게 되는데 이 때 이 프로토콜 변수의 레퍼런스를 뷰 컨트롤러 로 설정하고 선택된 셀의 index를 Custom Cell클래스의 index프로퍼티로 설정한다.

          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              let cell = tableView.dequeueReusableCell(withIdentifier: “ComponentProductCell”) as! ComponentProductCell
      
              …
              cell.index = indexPath.row
              cell.delegate = self
              …  
      
              return cell
          }
      

      물론 이 전에 뷰컨트롤러 클래스는 위임받을 동작에 대한 구현을 프로토콜 상속을 통해 구현해주어야 한다.

      extension ComponentProductVC: ComponentProductCellDelegate{
          func selectedInfoBtn(index: Int) {
              …
      }
      

      전에도 비슷한 동작을 구현했을 때는 Target-Action 으로 처리를 해주었던 기억이 있다.
      뭐가 더 나은방법이라 할순 없겠지만 디자인패턴을 적용하면서 iOS에서 자주 사용하는 Delegation에 대한 이해를 더 잘 할 수 있게되어서 좋은 경험이였다.

    • 야곰
      키 마스터
      • 글작성 : 37
      • 답글작성 : 580

      Notification 패턴을 사용하지 않고, Delegation 패턴을 사용한 이유가 궁금합니다 🙂

      • 쥬트
        참가자
        • 글작성 : 9
        • 답글작성 : 8

        Delegation 패턴은 iOS에 전반적으로 사용되는 패턴이라 생각하기 때문이였습니다.
        직접 Delegation 패턴으로 구현해보면서 이러한 패턴을 이해하는데 많은 도움이 된 것 같습니다. !!😀

        • 야곰
          키 마스터
          • 글작성 : 37
          • 답글작성 : 580

          그렇군요! 노티피케이션 패턴으로도 해결해 볼 수 있을 것 같으니 해본적이 없다면 도전해보는 것도 좋을것 같아요 🙂
          멋진글 고맙습니다!

        • 멍단비
          참가자
          • 글작성 : 10
          • 답글작성 : 98

          노티피케이션 받고 콜백클로저 도전도 추천드립니다 !

          저도 같은상황에서 델리게이트 패턴을 주로 이용했었는데, 화면이 많아지면 델리게이트 패턴 네이밍이 힘들고 추적하기도 힘들어서 바꿨어요ㅎㅎ.

1 답변 글타래를 보이고 있습니다
  • 답변은 로그인 후 가능합니다.

logo landscape small

사업자번호 : 743-81-02195
통신판매업 신고번호 : 제 2022-충북청주-1278 호
고객센터 : 카카오톡채널 @yagom