본문 바로가기
개발 블로그/아이폰개발

델리게이트(Delegate) 위임 패턴이란?

by snapshot 2019. 10. 23.

델리게이트란?

델리게이트의 정의를 위키 사전으로 한번 보자

위임 패턴

 

위임 패턴 - 제타위키

다음 문자열 포함...

zetawiki.com

간단히 어떤 객체가 할 일을 부분적으로 대신 처리한다.라고 정의될 수 있다.

 

아이폰 앱 개발을 하게 되면 자연스럽게.. 아니.. 당연히 알아야 하는 패턴 같다.

 

델리게이트 패턴은 TableView를 사용하게 되면 자연스럽게 TableviewDelegate, UITableViewDataSource를 구현하게 된다. TableviewDelegate는 이벤트를 담당하는 것이고 데이터 소스는 테이블 뷰에 적용되는 정보를 넘겨줄 때 사용을 한다.

 

정의처럼 우리가 테이블 뷰를 화면에 그려줄 때 우리는 셀의 갯 수, 섹션의 수, 그리고 TableViewCell의 정보, TableView Section 타이틀 또는 커스텀 View와 같은 정보들을 넘겨준다.

 

그 정보를 토대로 TableView는 화면에 적용되고 그에 대한 이벤트는 제공된 함수를 통해서 구현할 수 있다.

 

Delegate 패턴을 직접 구현해보자.!!!!!!!!!!!!!!!!!!!!!!

 

// 델리게이트를 제공하는 SecondView 

protocol SecondViewDelegate : class {
    func secondViewInfo(view : SecondView, index : Int)
}

class SecondView : UIView {
    weak var delegate : SecondViewDelegate?
    
    @IBAction func clickEventHandler(_ button:UIButton) {
        if let theDelegate = self.delegate {
            theDelegate.secondViewInfo(view: self, index: 0)
        }
    }
}

위에 코드를 설명을 해보겠다. 

일단 프로토콜을 만들고 class를 상속받는다. 이 이유는 뒤에 말해주겠다.

func은 SecondView와 인덱스를 파라미터로 생성을 한다. 

 

SecondeView에서는 delegate를 변수로 만들고 

프로토콜의 함수를 호출하는 곳에서 활용을 한다. 

delegate 변수는 weak를 또 받는다.

 

이건 class를 상속받는 것과 연관이 있다. https://popopo.tistory.com/126

 

ARC, 순환참조와 소유권 지시어 (iOS, xcode)

ARC, 순환참조와 소유권 지시어 (iOS, xcode) "iOS와 OS 의 메모리 관리와 멀티스레딩 기법" 이란 오래된 책을 다시 요즘에 읽어 소유권 지시어에 대한 내용을 적어 본다. ARC (Automatic Reference counting)은..

popopo.tistory.com

이것을 먼저 일고 오기 바란다. weak는 순환 참조를 방지하기 위해서 사용했다. 왜냐면 protocol의 함수에 SecondView 타입을 받기 때문이다.

그리고 weak를 사용했기 때문에 protocol은 당연히 class 타입으로 해야 한다. 

물론 프로토콜 func에서 SecondView을 제공하지 않고 바로 index를 사용했다면 class를 상속받지 않아도 된다. weak는 class 타입이 아니기 때문에 지워줘야 한다. 

 

 

// 델리게이트를 활용하는 FirstViewController

class FirstViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let view = SecondView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        view.delegate = self
        self.view.addSubview(view)
    }
}

extension FirstViewController : SecondViewDelegate {
    func secondViewInfo(view: SecondView, index: Int) {
        print("secondViewInfo== \(index)")

    }
}

여기에서는 SecondView를 생성해서 뷰에 add 해 주고 그 델리게이트는 self로 하여 받게 하였다. 

 

extension으로 하지 않아도 되지만 저렇게 분리해놓으면 나중에 지우기 편해서 나는 저런 식으로 구현을 한다. 

SecondViewDelegate를 상속받은 FirstClassFirstViewController의 extention은 이벤트가 생길 때마다 func secondViewInfo(view: SecondView, index: Int) 함수가 호출될 것이고 여기서 그에 대한 대응을 하면 된다. 

 

나는 이 패턴을 좋아하고 iOS 개발자라면 기본적으로 알아야 한다고 생각을 한다. 

직접 구현해보고 어떻게 이벤트가 적용되는지 몸으로 무조건 익혔으면 좋겠다. 

 

나의 코딩 스탠더드(기준)에 따라서 이벤트가 확실히 즉각적으로 일어날 때 그에 대한 구현은 다른 클래스에서 구현되길 바랄 때 구현을 한다. 

만약에 델리게이트 패턴이 없었다면 어떻게 될까..?

우리는 FirsFirstViewControllertClass에서 SecondView의 기능까지 모두 가지고 있어야 하기 때문에 유지 보수가 매우 힘들 것이다. 

SecondView가 다른 곳에서 사용한다고 치면 같은 코드들을 분리하지 못하고 여러 곳에서 고쳐야 하는 엄청나게 수고스러운 일이 생길 것이다. 

FirstViewController는 secondView를 알지만 SecondView는 어떤 클래스가 사용하는지 알 필요가 없기에 의존성이 100%로 없다고 할 수 없다. 하지만 각 클래스 맞게 구현되는 코드들은 분리될 수 있기 때문에 응집도는 높게 될 수 있다. 

 

 

댓글