Delegate Pattern
- 두 개의 클래스 A,B가 존재한다고 가정해보자. 만약 A에서 B의 어떠한 프로퍼티 값을 고치고 싶다면? 혹은 A에서 B로 데이터를 옮기고 싶다면? 우리는 Delegate Pattern을 사용해 볼 수 있다.
☀️ Delegate Pattern 예시(1)
Teacher는 cleaningArea 프로퍼티를 가지고 있고, Student는 Teacher의 cleaningArea값을 변화시킨다. 해당 과정을 delegate pattern을 통하여 구현해보자.
- ViewController간의 데이터 전달이 아닌, 일반 클래스 간의 데이터 전달의 예를 알아보자. 아래와 같은 protocol을 생성해보자.
// 청소를 시킬 수 있는
protocol CleanOrderable {
var cleaningArea: [String: Bool] { get set }
func notifyTodayCleanArea() -> [String]
}
- 아래와 같이 Teacher는 CleanOrderable 프로토콜을 채택하였기에 함수의 바디를 작성해주어야된다.
class Teacher: CleanOrderable {
var cleaningArea: [String : Bool]
var myClass: String
init(area: [String : Bool], myClass: String) {
self.cleaningArea = area
self.myClass = myClass
}
// 자신(teacher)의 cleaningArea를 던지는 함수
func notifyTodayCleanArea() -> [String] {
return cleaningArea.keys.map { String($0) }
}
}
- 그리고 Student는 deleagate 변수를 하나 생성해준다.
- 여기서 delegate은 결국 teacher로 바꿔치기된다.
- 즉, Student는 Teacher의 함수를 호출하여 Teacher의 cleaningArea의 값을 변경한다.
class Student {
var delegate: CleanOrderable?
func clean() {
let todayCleanTargetArea = delegate?.notifyTodayCleanArea()
todayCleanTargetArea?.forEach { area in
delegate?.cleaningArea.updateValue(true, forKey: area)
}
}
}
- 그리고 여기서 가장 중요한 점은 생성한 Student 객체의 delegate 변수를 teacher로 설정해주는 것이다. 그러면 최종적으로 delegate이 teacher로 바꿔치기되는 것이다!
let teacher = Teacher(area: ["복도": false, "교실": false], myClass: "1반")
let student = Student()
student.delegate = teacher
student.clean()
teacher.cleaningArea // ["복도": true, "교실": true]
원래는 tudent가 Teacher의 cleaningArea를 변경하려면, Student안에 Teacher를 프로퍼티로 가져서 변경해주면 되지만, 위와 같이 delegate pattern을 통하여 해결을 할 수 있다.
☀️ Delegate Pattern 예시 (2) - ViewController간의 데이터 전달
- 아래의 그림과 같이 SendViewController에서 ReceiveViewController로 데이터 전달을 delegate pattern을 통하여 해보자.
SendViewController의 textfield에 글을 쓰고 button을 누르면 dismiss가 되면서 textfield에 있는 text가 ReceiveviewController의 label에 나오게 된다.
- 아래와 같이 protocol을 하나 생성해준다.
protocol SendDataDelegate {
func sendData(data: String)
}
- 그리고 SendViewController에 delegate 변수를 하나 생성해준다. 그리고 delegate?.sendData를 통하여 원하는 데이터를 담아서 보낸다.- 실제로 함수를 실행하는 부분. (delegate는 ReceiveViewController로 바꿔치기된다.)
class SendViewController: UIViewController {
var delegate: SendDataDelegate?
@IBOutlet weak var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func myButtonClicked(_ sender: Any) {
guard let data = myTextField.text else { return }
**delegate?.sendData(data: data)**
dismiss(animated: true, completion: nil)
}
}
- ReceiveViewController에서는 sendViewController에서 선언한 Delegate이 자신(ReceiveViewController)임을 선언하고, SendDataDelegate을 채택하여 sendData 함수의 바디를 완성해준다.(실질적인 함수 실행은 SendViewController에서 진행된다.)
class ReceiveViewController: UIViewController {
@IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func plusButtonCliecked(_ sender: Any) {
guard let sendViewController = self.storyboard?.instantiateViewController(withIdentifier: "SendViewController") as? SendViewController else { return }
**sendViewController.delegate = self**
present(sendViewController, animated: true)
}
}
extension ReceiveViewController: **SendDataDelegate** {
func sendData(data: String) {
**myLabel.text = data**
}
}
🔥 총정리
만약 A,B 두개의 ViewController가 존재하고 B의 데이터를 A에게 전달하고 싶다면?
ViewController A ( 데이터를 전달 받는)
- protocol을 채택(protocol 내의 함수를 완성시켜주어야된다.)
- ViewController B 안의 delegate 변수의 위임자가 자신임을 선언해준다.
- ex) viewControllerB.delegate = self
ViewController B (데이터를 전달하는)
- delegate 변수를 선언해준다.
- ex) var delegate: ProtocolName?
- 실제 함수를 발동시키는 코드를 작성한다.
- delegate?.protocolFunc()
- 프로토콜을 정의해주기!
'iOS' 카테고리의 다른 글
[iOS] 메모리 구조/ARC(Automatic Reference Count) (0) | 2023.02.04 |
---|---|
[iOS] 의존성 주입 (0) | 2023.02.04 |
[iOS] Queue 구현하기 (0) | 2023.02.04 |
[iOS] Priority(Autolayout) (0) | 2023.02.03 |
[iOS] prepareForReuse() (0) | 2023.02.03 |