Delegate Pattern

이원희·2020년 12월 31일
0

📱 iOS

목록 보기
11/24
post-thumbnail

오늘은 Delegate Pattern에 대해 알아보자.
Delegate Pattern은 iOS 개발하다보면 정말 많이 보게된다.
나는 TableView를 사용하면서 처음 봤었다.
그때는 protocol에 대한 이해도 없었고, 타이트한 일정으로 제대로 알아볼 생각을 못했었다.
그냥 TableView를 사용할때 DataSourceDelegate를 사용할 수 있구나.
cell을 클릭해서 이동하고 싶을때 Delegate를 사용할 수 있구나 싶었다.
Delegate는 iOS를 개발할때에 많이 만나고 그만큼 완벽한 이해가 필요하다 생각한다.


Delegate

Delegate 혹은 Delegation을 검색하다보면

Delegation은 일부 클래스의 책임을 다른 클래스의 인스턴스에게 위임 또는 전달할 수 있는 디자인 패턴

위와 같은 문구를 자주 접하게 된다.

쉽게 말하면 Delegation은 내가 해야 할일을 다른 인스턴스로 넘겨버린다고 할 수 있다.

  • UITableView를 생각해보면, table cell을 클릭했을때 동작을 UITableView가 처리해야하지만 UITableViewDelegate로 떠넘겨 버린다.
  • UITextView를 생각해보면, textView의 수정이 끝났는지 확인을 UITextView가 처리해야하지만 UITextViewDelegate로 떠넘겨 버린다.

Delegation을 이해하는데 아래 내용을 생각하면서 봐보자.

  • 수신자 Receiver
  • 대리자 Delegate
  • 대리자에게 수신자 자신을 전달

UITableView와 Delegate

그럼 우리는 익숙한 UITableView로 이해를 해보자.
UITableVeiw에서 table cell을 클릭하여 다른 화면으로 이동하고 싶다면 어떻게 코드를 작성할까?

class ViewController: UIViewController {
    
    @IBOutlet weak var table: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        table.delegate = self
    }
}

extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let secondViewController = UISecondViewController()
        self.navigationController?.pushViewController(secondViewController, animated: true)
    }
}

위의 코드는 익숙할거다.
그래도 하나씩 뜯어보자.

  • TableViewIBOutlet으로 지정해줬다.
  • table.delegate = selfTableViewdelegate를 지정해줬다.
  • ViewControllerUITableViewDelegate를 채택하고, didSelectRowAt 메서드에서 해당 작업을 작성해줬다.

결과적으로 ViewControllertable은 cell 클릭시 해야할 일을 UITableViewDelegate에 떠넘기게 되었다.


Delegate와 Protocol

본격적으로 내용을 살펴보기 전에

ViewControllerUITableViewDelegate를 채택

라고 했는데 채택!! 채택!! 뭔가 생각나지 않나?!

이전 프로토콜 포스팅에서 프로토콜은 채택한다고 했다.
그렇다면 DelegateProtocol로 구성되어 있을까?!

❗️맞다!!
이 부분은 잠시 후 다시 다룰 것이니 지금은 "DelegateProtocol로 구성되어 있으므로 채택한다고 해야하는구나"까지만 알아두자.


UITableViewDelegate

우리는 먼저 TableViewDelegate를 사용하는 과정과 맨 위에서 알아두라고 했던 내용과 짝지어 볼것이다.

  • table.delegate = selfTableViewdelegate를 지정해줬다.
  • ViewControllerUITableViewDelegate를 채택하고, didSelectRowAt 메서드에서 해당 작업을 작성해줬다.
  • 수신자 Receiver
  • 대리자 Delegate
  • 대리자에게 수신자 자신을 전달

대리자 Delegate

위의 코드에서 대리자는 누구일까?
❗️ UITableViewDelegate이다.
tableView로부터 cell 클릭시 해야할 일을 위임 받았기 때문이다.

수신자 Receiver

위의 코드에서 수신자는 누구일까?
❗️ ViewControllertable 프로퍼티이다.
UITableViewDelegate의 결과를 table이 받기 때문이다.

대리자에게 수신자 자신을 전달

table.delegate = self를 통해 대리자에게 수신자 자신을 전달하고 있다.


Delegate Pattern

우리는 위에서 UITableViewDelegate를 통해 Delegation을 알아봤다.
그럼 Delegation은 Apple이 미리 만들어 놓은 것만 사용할 수 있는걸까?!

오늘 포스팅 제목을 생각해보면 힌트를 얻을 수 있다.
우리는 Delegate Pattern을 알아보기로 했다.
위에서는 Delegation이 어떤 것이고, 어떻게 설정?사용?하는지 알아봤고 이해를 위해 가장 많이 접해봤을 예시를 가져온 것 뿐이다.
Pattern은 말 그대로 패턴일뿐여서 iOS에서 자주 쓰이지만 다른 언어에도 적용할 수 있다.

사실 내가 처음 Delegate를 접했을때 어려웠던 이유는 패턴이라고 생각하지 못했고, 그래서 Apple이 미리 만들어 놓은 것만 사용할 수 있다 생각했었기 때문이다.
그리고 Delegate PatternProtocol을 사용하게되는데 그당시 Protocol에 대한 이해가 없었다.
또한, 수신자/대리자/대리자에게 수신자 자신을 전달을 이해하지 못했다.
(근데... 많이 사용해서 감으로 이해하게 되었다...)

그럼 우리는 수신자/대리자/대리자에게 수신자 자신을 전달을 생각하면서 Delegate Pattern을 만들어보자.

protocol

왼쪽이 첫번째 화면이고, 버튼을 누르면 오른쪽 화면으로 넘어간다.
오른쪽 화면에서 버튼을 누르면 첫번째 화면의 label의 텍스트가 바뀌도록 구현하고 싶다.

흠...
두번째 화면에서 버튼을 누르는데 첫번째 화면의 텍스트가 바껴...?
❗️그럼 첫번째 화면의 텍스트 바꾸는 부분을 다른 애한테 위임해야겠네..?!

ViewController

class ViewController: UIViewController {
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func touchUpButton(_ sender: Any) {
        guard let secondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "second") as? SecondViewController else {
            return
        }
        secondViewController.secondButtonDelegate = self
        self.present(secondViewController, animated: true, completion: nil)
    }
}

extension ViewController: SecondeButtonDelegate {
    func changeButton() {
        self.label.text = "❗️Delegate를 눌러서 바꼈다!❗️"
    }
}

SecondController

class SecondViewController: UIViewController {
    @IBOutlet weak var button: UIButton!
    
    var secondButtonDelegate: SecondeButtonDelegate? = nil
    
    @IBAction func touchUpButton(_ sender: Any) {
        self.secondButtonDelegate?.changeButton()
    }
}

protocol SecondeButtonDelegate {
    func changeButton()
}

SecondController에 Delegate protocol을 정의했다.
protocol은 함수의 구현부는 정의하지 않으므로 정의부만 정의했다.

ViewController에서 버튼을 클릭하면 secondViewController.secondButtonDelegate = self로 자신을 넘겨주고 있다.
(ViewController수신자 seconViewController.secondButtonDelegate대리자)

SecondController에서 버튼을 클릭하면 seconButtonDelegatechangeButton()을 실행한다.
대리자는 수신자 객체의 메소드를 대신 실행해주고 있다.
(Label의 텍스트를 바꿔줌)

원하는대로 잘 동작하는걸 확인할 수 있다.


마무리

오늘은 delegate에 대해서 알아봤다.
그럼 이만👋

0개의 댓글