두 개의 클래스 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로 바꿔치기되는 것이다!
그리고 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에게 전달하고 싶다면?