💡 학교 선생님과 학생 예
- 학생(객체 A)이 질문을 하면, 선생님(Delegate, 객체 B)이 대신 대답해준다.
- 즉, 학생은 "답하는 로직"을 몰라도, 선생님인 "대답해줄 사람"만 알고 있으면 된다!
| 구성요소 | 설명 |
|---|---|
| Protocol | 어떤 일을 대신해줄지 정의 (약속) |
| Delegate | 일을 대신 해주는 객체 (보통 ViewController) |
| Owner | Delegate에게 일을 맡기는 객체 (보통 View) |
weak으로 선언)protocol MyViewDelegate: AnyObject {
func didTapButton()
}
AnyObject: 클래스 타입에서만 사용 가능하게weak 선언을 위해 필요class MyView: UIView {
weak var delegate: MyViewDelegate?
let button = UIButton(type: .system)
override init(frame: CGRect) {
super.init(frame: frame)
button.setTitle("클릭!", for: .normal)
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
addSubview(button)
// ...
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func buttonTapped() {
delegate?.didTapButton()
}
}
delegate를 통해 이벤트를 외부로 전달!class MyViewController: UIViewController, MyViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let MyView = MyView()
MyView.delegate = self // delegate 연결
view.addSubview(MyView)
// ...
}
func didTapButton() {
print("버튼 클릭!")
}
}
View에서 버튼 클릭! → ViewController로 알려주기 (이벤트 처리)
View: 버튼 클릭 이벤트를 처리하지 않고, "대신 해줘!" 하고 delegate에게 전달
ViewController: 실제 동작(프린트, 화면 전환 등)을 구현
💡 왜 사용할까?
- 재사용성: 로직을 분리하니까, 여러 곳에서 사용할 수 있음
- 유연함: delegate만 바꾸면 행동도 바뀜
- 낮은 결합도: View는 로직을 몰라도 됨. 그냥 delegate에게 시킴
// 🚨 retain cycle 예
class A {
var delegate: B? // 강한 참조
}
class B {
var classA: A? // 강한 참조
}
strong으로 참조 → 메모리에서 안 사라짐❗️protocol MyViewDelegate: AnyObject {
func didTapButton()
}
AnyObject: 클래스 타입만 채택 가능하게 함AnyObject 제약을 붙여야 weak 사용 가능 → weak은 클래스 인스턴스에만 쓸 수 있기 때문class MyView {
weak var delegate: MyViewDelegate?
}
delegate는 참조만 하고, 소유 ❌weak으로 선언해야 ViewController가 메모리에서 해제될 수 있음 (순환 참조 방지)