
한 객체가 해야 할 일을 다른 객체에게 위임하는 패턴. 프로토콜로 "무엇을 위임할 것인가"를 명세하고, 위임받은 객체가 이를 구현한다.
위임할 동작을 프로토콜로 명세.
protocol ButtonDelegate: AnyObject {
func didTapButton()
}
AnyObject 채택은 weak 참조를 가능하게 하기 위함 → 순환 참조 방지 (7/8 ARC 내용과 연결).
delegate 프로퍼티를 weak var로 선언하고, 이벤트 발생 시 호출.
class Button {
weak var delegate: ButtonDelegate?
func tap() {
delegate?.didTapButton()
}
}
프로토콜을 채택하고, 자신을 delegate로 등록.
class ViewController: ButtonDelegate {
let button = Button()
init() {
button.delegate = self // 자신을 위임 객체로 등록
}
func didTapButton() {
print("Button was tapped!")
}
}
let vc = ViewController()
vc.button.tap() // "Button was tapped!"
Button이 delegate를 강하게 참조하고, ViewController가 Button을 강하게 참조하면 순환 참조 발생 → 둘 다 메모리에서 해제 안 됨.
weak var delegate로 선언하면 RC를 증가시키지 않아서 순환 참조가 끊김.
직접 참조 대신 프로토콜을 통해 통신하므로 Delegator는 Delegate가 누구인지 알 필요가 없음. ButtonDelegate 프로토콜만 채택하면 어떤 클래스든 delegate가 될 수 있어서 결합도가 낮아지고 교체가 쉬워짐.
UIKit에서 UITableViewDelegate, UITextFieldDelegate 등이 전부 이 패턴으로 동작함.