목차
반응형
내배캠 iOS 앱 개발 입문 1주차 강의에서 제공된 Counter 앱을 기반으로, UIKit에서 가장 널리 쓰이는 디자인 패턴 중 하나인 Delegate(델리게이트) 패턴을 학습해보려고 합니다.
Delegate 패턴이란?
Delegate는 말 그대로 위임이라는 뜻을 가지고 있습니다. iOS에서 Delegate 패턴은 한 객체가 발생시킨 이벤트를 다른 객체에게 처리 위임하는 구조를 의미합니다.
Apple 공식 문서에 따르면
A delegate acts on behalf of, or in coordination with, another object.
Delegate 패턴을 언제 사용하나?
- View는 사용자 이벤트(버튼 클릭 등)를 감지할 수 있지만, 로직 처리까지 책임지게 하면 역할이 무거워지고 재사용이 어렵습니다.
- Controller에 처리를 위임하면 View는 "알림"만 하고, 실제 처리는 다른 객체가 담당할 수 있어 역할 분리가 명확해집니다.
예시 상황
- 커스텀 뷰 내부에서 버튼 클릭 → ViewController에서 처리하고 싶을 때
- UITableView, UICollectionView 등 시스템 컴포넌트들도 Delegate를 활용
Delegate 패턴의 핵심 개념
- 이벤트를 발생시키는 객체(주로 View)는 delegate 프로토콜을 정의
- delegate 프로퍼티는 weak으로 선언하여 메모리 순환을 방지
- 실제 동작 처리는 delegate를 구현한 객체(ViewController 등)가 수행
- View와 Controller 간의 결합도를 낮춰 유연한 설계 가능
Delegate 패턴의 구성 요소
Protocol | 위임할 메서드 정의 (ex. didTapButton()) |
Delegate 프로퍼티 | weak으로 선언해 메모리 순환 방지 |
Delegate 메서드 호출 | View에서 이벤트 발생 시 호출 |
실제 구현체 | ViewController에서 프로토콜 채택 + 구현 |
Delegate 패턴의 장점
- 역할 분리: View는 UI만, Controller는 로직만 담당
- 재사용성: View는 다양한 컨트롤러에서 재사용 가능
- 확장성: 다양한 이벤트 대응 가능 (버튼, 제스처 등)
Counter 앱에 적용한 Delegate 패턴 코드
1. Protocol 정의
protocol CounterViewDelegate: AnyObject {
func counterViewDidTapIncrementButton(_ counterView: CounterView)
func counterViewDidTapDecrementButton(_ counterView: CounterView)
func counterViewDidTapReSetButton(_ counterView: CounterView)
}
- AnyObject: class 전용으로 제한 (메모리 순환 방지를 위해 weak 사용 가능하게)
- 메서드 네이밍은 counterViewDidTap...처럼 구체적으로 작성
2. CounterView 클래스
class CounterView: UIView {
weak var delegate: CounterViewDelegate?
private let incrementButton = UIButton()
private let decrementButton = UIButton()
private let reSetCounterButton = UIButton()
override init(frame: CGRect) {
super.init(frame: frame)
setTarget()
}
private func setTarget() {
incrementButton.addTarget(self, action: #selector(didTapIncrementButton), for: .touchUpInside)
decrementButton.addTarget(self, action: #selector(didTapDecrementButton), for: .touchUpInside)
reSetCounterButton.addTarget(self, action: #selector(didTapReSetButton), for: .touchUpInside)
}
@objc private func didTapIncrementButton() {
delegate?.counterViewDidTapIncrementButton(self)
}
@objc private func didTapDecrementButton() {
delegate?.counterViewDidTapDecrementButton(self)
}
@objc private func didTapReSetButton() {
delegate?.counterViewDidTapReSetButton(self)
}
}
- View는 어떤 버튼이 눌렸는지만 판단하고, 실제 처리 로직은 위임
- View는 Controller가 누구인지 몰라도 delegate만 호출하면 됨 → 느슨한 연결 (Loosely Coupled)
3. CounterViewController 클래스
class CounterViewController: UIViewController, CounterViewDelegate {
private let counterView = CounterView()
private var count = 0
override func loadView() {
view = counterView
}
override func viewDidLoad() {
super.viewDidLoad()
counterView.delegate = self
}
func counterViewDidTapIncrementButton(_ counterView: CounterView) {
count += 1
print("+1: \(count)")
}
func counterViewDidTapDecrementButton(_ counterView: CounterView) {
count -= 1
print("-1: \(count)")
}
func counterViewDidTapReSetButton(_ counterView: CounterView) {
count = 0
print("Reset: \(count)")
}
}
- ViewController는 프로토콜을 채택하고 실제 이벤트 처리를 담당
- View는 재사용 가능하고, Controller는 책임을 분리해서 관리
📘 참고 문서
반응형
'iOS > UIKit' 카테고리의 다른 글
[ UIKit ] SwiftUI만 공부하던 내가 UIKit MVVM에서 클로저를 처음 마주쳤을 때 (0) | 2025.04.09 |
---|---|
[ UIKit ] Combine으로 상태를 바인딩하는 방법 (0) | 2025.04.06 |
[ UIKit ] UISlider (20) | 2024.02.03 |
[ UIKit ] UIButton (19) | 2024.01.28 |
[UIKit ] UILabel (17) | 2024.01.27 |
반응형
내배캠 iOS 앱 개발 입문 1주차 강의에서 제공된 Counter 앱을 기반으로, UIKit에서 가장 널리 쓰이는 디자인 패턴 중 하나인 Delegate(델리게이트) 패턴을 학습해보려고 합니다.
Delegate 패턴이란?
Delegate는 말 그대로 위임이라는 뜻을 가지고 있습니다. iOS에서 Delegate 패턴은 한 객체가 발생시킨 이벤트를 다른 객체에게 처리 위임하는 구조를 의미합니다.
Apple 공식 문서에 따르면
A delegate acts on behalf of, or in coordination with, another object.
Delegate 패턴을 언제 사용하나?
- View는 사용자 이벤트(버튼 클릭 등)를 감지할 수 있지만, 로직 처리까지 책임지게 하면 역할이 무거워지고 재사용이 어렵습니다.
- Controller에 처리를 위임하면 View는 "알림"만 하고, 실제 처리는 다른 객체가 담당할 수 있어 역할 분리가 명확해집니다.
예시 상황
- 커스텀 뷰 내부에서 버튼 클릭 → ViewController에서 처리하고 싶을 때
- UITableView, UICollectionView 등 시스템 컴포넌트들도 Delegate를 활용
Delegate 패턴의 핵심 개념
- 이벤트를 발생시키는 객체(주로 View)는 delegate 프로토콜을 정의
- delegate 프로퍼티는 weak으로 선언하여 메모리 순환을 방지
- 실제 동작 처리는 delegate를 구현한 객체(ViewController 등)가 수행
- View와 Controller 간의 결합도를 낮춰 유연한 설계 가능
Delegate 패턴의 구성 요소
Protocol | 위임할 메서드 정의 (ex. didTapButton()) |
Delegate 프로퍼티 | weak으로 선언해 메모리 순환 방지 |
Delegate 메서드 호출 | View에서 이벤트 발생 시 호출 |
실제 구현체 | ViewController에서 프로토콜 채택 + 구현 |
Delegate 패턴의 장점
- 역할 분리: View는 UI만, Controller는 로직만 담당
- 재사용성: View는 다양한 컨트롤러에서 재사용 가능
- 확장성: 다양한 이벤트 대응 가능 (버튼, 제스처 등)
Counter 앱에 적용한 Delegate 패턴 코드
1. Protocol 정의
protocol CounterViewDelegate: AnyObject {
func counterViewDidTapIncrementButton(_ counterView: CounterView)
func counterViewDidTapDecrementButton(_ counterView: CounterView)
func counterViewDidTapReSetButton(_ counterView: CounterView)
}
- AnyObject: class 전용으로 제한 (메모리 순환 방지를 위해 weak 사용 가능하게)
- 메서드 네이밍은 counterViewDidTap...처럼 구체적으로 작성
2. CounterView 클래스
class CounterView: UIView {
weak var delegate: CounterViewDelegate?
private let incrementButton = UIButton()
private let decrementButton = UIButton()
private let reSetCounterButton = UIButton()
override init(frame: CGRect) {
super.init(frame: frame)
setTarget()
}
private func setTarget() {
incrementButton.addTarget(self, action: #selector(didTapIncrementButton), for: .touchUpInside)
decrementButton.addTarget(self, action: #selector(didTapDecrementButton), for: .touchUpInside)
reSetCounterButton.addTarget(self, action: #selector(didTapReSetButton), for: .touchUpInside)
}
@objc private func didTapIncrementButton() {
delegate?.counterViewDidTapIncrementButton(self)
}
@objc private func didTapDecrementButton() {
delegate?.counterViewDidTapDecrementButton(self)
}
@objc private func didTapReSetButton() {
delegate?.counterViewDidTapReSetButton(self)
}
}
- View는 어떤 버튼이 눌렸는지만 판단하고, 실제 처리 로직은 위임
- View는 Controller가 누구인지 몰라도 delegate만 호출하면 됨 → 느슨한 연결 (Loosely Coupled)
3. CounterViewController 클래스
class CounterViewController: UIViewController, CounterViewDelegate {
private let counterView = CounterView()
private var count = 0
override func loadView() {
view = counterView
}
override func viewDidLoad() {
super.viewDidLoad()
counterView.delegate = self
}
func counterViewDidTapIncrementButton(_ counterView: CounterView) {
count += 1
print("+1: \(count)")
}
func counterViewDidTapDecrementButton(_ counterView: CounterView) {
count -= 1
print("-1: \(count)")
}
func counterViewDidTapReSetButton(_ counterView: CounterView) {
count = 0
print("Reset: \(count)")
}
}
- ViewController는 프로토콜을 채택하고 실제 이벤트 처리를 담당
- View는 재사용 가능하고, Controller는 책임을 분리해서 관리
📘 참고 문서
반응형
'iOS > UIKit' 카테고리의 다른 글
[ UIKit ] SwiftUI만 공부하던 내가 UIKit MVVM에서 클로저를 처음 마주쳤을 때 (0) | 2025.04.09 |
---|---|
[ UIKit ] Combine으로 상태를 바인딩하는 방법 (0) | 2025.04.06 |
[ UIKit ] UISlider (20) | 2024.02.03 |
[ UIKit ] UIButton (19) | 2024.01.28 |
[UIKit ] UILabel (17) | 2024.01.27 |