Open Do-hyun-Kim opened 1 year ago
프로토콜을 이용해서 클래스나 구조체가 자신의 권한을 다른 타입의 인스턴스에게 위임하여 일을 처리하는 방식의 디자인 패턴 (어떤 객체가 해야할 일을 대신해서 처리해주는 것)
UITableView class
는 UITableViewDelegate
와 UITableViewDataSource
프로토콜을 사용하여 테이블 뷰 상호작용, 셀 표시 및 테이블 뷰 레이아웃 변경을 관리한다.CLLocationManager
는 CLLocationManagerDelegate
를 사용하여 위치 관련 데이터를 앱에 보고한다. 예를들어 iPhone의 GPS 좌표가 있다.UITextView
는 UITextViewDeleagte
를 사용하여 텍스트 뷰의 변경 사항을 보고한다. 새로운 문자 삽입, 선택 변경 및 텍스트 편집이 중단될 때와 같은 경우이다.
UITableViewDelegate
, UITableViewDataSource
, UICollectionViewDelegate
.. 등이 있으며 iOS에서 발생하는 UI 이벤트에 대한 처리를 delegate
프로토콜을 채택하는 UIViewController
에서 대신 처리해주도록 한다.protocol DelegateProtocol {
func tappedButton(value: String)
...
}
class Delegator {
var delegate: DelegateProtocol?
lazy var button: UIButton = {
let button = UIButton()
button.addTarget(self, action: #selector(tappedButton), for: .touchUpInside)
return button
}()
init() {}
@objc func tappedButton() {
delegate?.tappedButton(value: "Tapped Button")
}
}
class Delegatee: DelegateProtocol {
var delegator = Delegator()
init() {
delegator.delegate = self
}
func tappedButton(value: String) {
print("value: ", value)
}
}
위임받는 객체(delegatee)에서 위임해주는 객체(delegator)의 delegate에 위임받는 객체를 참조하게 하는 순간(delegator.delegate = self
) '강한(strong
)참조가 발생하여 '순환참조(retain cycle
)' 가 발생할 위험이 있다.
이 때문에 delegate 프로토콜 타입을 weak
키워드를 선언함으로서 참조 카운트(reference count
)를 증가시키지 않도록하여 순환참조를 방지하도록 할 필요가 있다. 이때 protocol 은 값타입도 참조타입도 아닌 추상타입이기 때문에 delegate 프로토콜이 AnyObject
프로토콜을 채택하게 하여 컴파일러에게 참조타입임을 알려야 한다. 이렇게 해야만 weak
키워드를 사용하여 참조 카운트를 관리할 수 있다.
protocol DelegateProtocol: AnyObject {
func tappedButton(value: String)
...
}
class Delegator {
weak var delegate: DelegateProtocol?
...
iOS 에서 delegate 패턴은 어떤 뷰의 이벤트에 대한 처리를 다른 뷰에서 해줄때 사용할 수 있는 유용한 패턴이다. delegate 패턴을 사용하지 않게 될 경우, 전역변수를 사용한다거나 UserDefaults
등을 사용하여 무분별하게 로컬에 데이터를 저장하고 사용함으로서 불편성과 위험성을 증가시키는 코드를 작성하게 될 수 있다.
어떠한 객체가 해야할 일을 다른 객체에게 위임하는 것
대리자 (Delegate) : 수신자를 대신하여 처리할 대리자
*UITextFieldDelegate 사용
class ViewController: UIViewController, UITextFieldDelegate {
let textField = UITextField()
override func viewDidLoad() { super.viewDidLoad() // delegate를 대리자로 설정해주기 self.textField.delegate = self } }
2. 메서드 구현
```swift
// 텍스트필드가 뷰컨에게 "작업이 끝났어 END 입력해" 라고 전달
func textFieldDidEndEditing(_ textField: UITextField) {
textField.text = "END"
}
// 텍스트필드가 뷰컨에게 "리턴버튼 누르면 키보드 내려도 돼" 라고 전달
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
}
->실제로는 UITextField의 동작이지만 ViewController가 메서드를 전달받아 대신 작업을 한다.
Delegate 패턴을 활용하는 경우를 예를 들어 설명하시오.
Delegate Pattern
이란 "객체가 자신의 책임을 다른 객체에게 위임(delegate)하는 디자인 패턴" 이라고 한다.UITableViewDelegate
,UICollectionViewDelegate
가 있습니다. 이 같은 경우 책임을 ViewController 에게 위임하여 기능을 대신 수행하도록 한다.Delegate Pattern
이 다른 클래스에도 활용이 될 경우에상속
을 활용 하는 것보다 적절 합니다.Delegate Pattern 장점
Protocol
을 사용하여 코드의 재사용성을 확보할 수 있으며, 유지보수 또한 쉽다.delegate Pattern
같은 경우 상속을 하지 않기 때문에 캡슐화를 파괴하지 않아도 되며 유연성을 부여 할 수 있다.Delegate Pattern 단점
nil
값이 들어가지 않아야 한다.nil
값이 포함된다면 크래시 오류가 발생한다.delegate Property
를 정의할 때weak
키워드를 선언하지 않을 경우Strong Reference Cycle
이 발생할 수 있다.Delegate Pattern
📝 참고 사이트