Delegate Pattern 왜 사용하는 걸까?
과제나 강의를 들어도 꼭 나오는 델리게이트 패턴은 정말 많이 쓰이는 것 같지만 정작 왜 사용하는지 모르고 사용하는 것 같은 느낌이 들어 개념을 한번 잡아보려고 한다.
Delegate Pattern 이란
객체가 자신의 책임을 다른 객체에게 위임하는 디자인 패턴
테이블뷰는 셀을 탭했을 때 어떤 행동을 할지에 대한 책임을 뷰컨트롤러에게 UITableViewDelegate 를 사용하여 위임한다.
테이블 뷰 외에도 콜렉션뷰 , 텍스트필드 등 많은 UI 요소들이 델리게이트 패턴을 사용해 다른 객체에게 책임을 위임하고 있다.
왜 위임을 하는 걸까?
UI요소에서의 Delegate Pattern
셀을 탭하면 테이블 뷰는 탭 이벤트를 받는다. 테이블뷰가 탭 이벤트를 받으면 델리게이트의 didSelectRowAt 메소드를 실행 시킨다. 이벤트를 받았을 때 어떤 행동을 할건지 델리게이트에게 위임 하는 것이다.
보통은 뷰컨트롤러에 tableView.delegate = self 와 같은 코드를 작성해 뷰컨트롤러의 인스턴스 자신을 위임자로 설정하고 didSelectRowAt 메소드에 셀을 탭했을 때 어떤 행동을 할지 정의한다.
테이블뷰가 알아서 다 하면 될 것 같은데 굳이 객체에게 위임하는 이유는 무엇일까?
우리가 UITableView 내부 코드를 수정할 수 없기 때문
셀이 탭되었을 때 어떤 행동을 할지 상황에 따라 다르기 때문에 개발자가 코드를 작성해야 한다. 하지만 우리는 테이블 뷰 안의 코드를 수정 할 수 없기 때문에 다른 객체에서 코드를 작성해준 뒤 테이블 뷰가 그 객체의 코드를 호출해줘야 한다.
이때 테이블뷰와 객체를 연결해주는 방식이 Delegate Pattern 이다.
예시를 한번 보자
protocol StudentDelegate: AnyObject {
func receiveMessage(message: String)
}
- Protocol 정의 : 먼저, 학생이 받을 수 있는 메시지를 정의하는 프로토콜을 작성한다.
class Student {
weak var delegate: StudentDelegate?
func sendMessageToTeacher(message: String) {
delegate?.receiveMessage(message: message)
}
}
- Student 클래스 작성 : 학생 클래스는 위에서 정의한 프로토콜을 채택하여 메시지를 받을 준비를 한다.
class Teacher: StudentDelegate {
let student = Student()
init() {
student.delegate = self
}
func sendMessageToStudent(message: String) {
student.sendMessageToTeacher(message: message)
}
func receiveMessage(message: String) {
print("학생이 메시지를 받았습니다: \\(message)")
}
}
- Teacher 클래스 작성 : 선생님 클래스는 학생에게 메시지를 전달하고 학생으로 부터 응답을 받는다.
let teacher = Teacher()
teacher.sendMessageToStudent(message: "금요일에 모의고사가 있습니다.")
- 선생님이 학생에게 메세지를 보내고 학생이 그에 대한 응답을 받는다.
이렇게 프로토콜을 사용해 델리게이트 패턴을 구현하면 훨씬 더 유연하고 재사용 가능한 코드를 만들 수 있다.
실제 사용할 때 두개의 뷰컨트롤러를 연결하는 예시를 한번 보자
protocol DataTransferDelegate: AnyObject {
func sendData(data: Any)
}
class ViewControllerB: UIViewController {
weak var delegate: DataTransferDelegate?
// 데이터를 처리하는 메서드
func processData(data: Any) {
// 받은 데이터를 처리하는 코드
}
}
데이터를 받는 ViewControllerB 를 작성하여 프로토콜을 채택한다.
class ViewControllerA: UIViewController, DataTransferDelegate {
let viewControllerB = ViewControllerB()
override func viewDidLoad() {
super.viewDidLoad()
viewControllerB.delegate = self
}
// DataTransferDelegate 프로토콜 메서드 구현
func sendData(data: Any) {
// ViewControllerB로부터 전달받은 데이터를 처리하는 코드
viewControllerB.processData(data: data)
}
// 데이터를 전달하는 메서드
func sendDataToViewControllerB() {
let dataToSend: Any = // 전달할 데이터
viewControllerB.delegate?.sendData(data: dataToSend)
}
}
class ViewControllerB: UIViewController {
weak var delegate: DataTransferDelegate?
// 데이터를 처리하는 메서드
func processData(data: Any) {
// 받은 데이터를 처리하는 코드
}
}
ViewControllerA에서 ViewControllerB로 데이터 전달하기 위해 ViewControllerB 의 delegate 에 자신을 할당하고 데이터를 전달 한다.
class ViewControllerB: UIViewController {
weak var delegate: DataTransferDelegate?
// 데이터를 처리하는 메서드
func processData(data: Any) {
// 받은 데이터를 처리하는 코드
}
}
ViewControllerB는 전달받은 데이터를 처리하는 메서드를 구현 한다.
이렇게 하면 ViewControllerA에서 ViewControllerB로 데이터를 전달하고, ViewControllerB는 전달받은 데이터를 처리할 수 있다. 이때 ViewControllerB는 ViewControllerA에게 의존하지 않고, 데이터 전달에만 집중할 수 있으며, ViewControllerA는 ViewControllerB에게 데이터를 전달하고 결과를 받는 역할을 수행한다.
'◽️ Programming > T I L' 카테고리의 다른 글
ToDoList 만들기 (5) 캘린더 추가 (0) | 2024.03.28 |
---|---|
ToDoList 앱 만들기 (4) (1) | 2024.03.27 |
ToDoList 앱 만들기 (3) (2) | 2024.03.25 |
MVC 패턴 적용하여 테이블 뷰 구성하기 (1) | 2024.03.22 |
App 화면 이동 및 데이터 전달 4가지 방법 (0) | 2024.03.21 |