각각이 어떤 방식으로 사용되는지
언제 사용되는지
Delegate
는 보통 Protocol 을 정의하여 사용합니다.
예제코드
// 1) Delegate 프로토콜 선언
protocol SomeDelegate {
func someFunction(someProperty: Int)
}
class SomeView: UIView {
// 2) 순환 참조를 막기 위해 weak으로 delegate 프로퍼티를 가지고 있음
weak var delegate: SomeDelegate?
func someTapped(num: Int) {
// 3) 이벤트가 일어날 시 delegate가 동작하게끔 함
delegate?.someFunction(someProperty: num)
}
}
// 4) Delegate 프로토콜을 따르도록 함
class SomeController: SomeDelegate {
var view: SomeView?
init() {
view = SomeView()
// 6) delegate를 자신으로 설정
view?.delegate = self
someFunction(someProperty: 0)
}
// 5) Delegate 프로토콜에 적힌 메소드 구현
func someFunction(someProperty: Int) {
print(someProperty)
}
}
let someController = SomeController()
// prints 0
장점
엄격한 Syntax
로 인해 프로토콜에 필요한 메소드들이 명확하게 명시되어 있습니다.
프로코콜에 정의되어 있는 메소드
들을 구현하지 않으면 컴파일 시 경고
혹은 에러
가 발생합니다.
커뮤니케이션 과정을 유지하고 모니터링하는 제 3의 객체(NotificationCenter)
가 필요하지 않습니다.
단점
많은 줄의 코드
가 필요합니다.
delegate 설정에 nil이 들어가지 않게 주의해야 합니다. (crash 주된 원인)
많은 객체들에게 이벤트를 알리는것이 어렵고 비효율적 입니다.
NotificationCenter
라는 싱글턴 객체 를 통해서 이벤트들의 발생 여부를 옵저버를 등록한 객체
들에게 Notification
을 post
하는 방식으로 사용합니다.
NotificationName
이라는 key 값
을 통해 보내고 받을 수 있습니다.
예제 코드
// 1) Notification을 보내는 ViewController
class PostViewController: UIViewController {
@IBOutlet var sendNotificationButton: UIButton!
@IBAction func sendNotificationTapped(_ sender: UIButton) {
guard let backgroundColor = view.backgroundColor else { return }
// Notification에 object와 dictionary 형태의 userInfo를 같이 실어서 보낸다.
NotificationCenter.default.post(name: Notification.Name("notification"), object: sendNotificationButton, userInfo: ["backgroundColor": backgroundColor])
}
}
// 2) Notification을 받는 ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 옵저버를 추가해 구독이 가능하게끔 함
NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived(notification:)), name: Notification.Name("notification"), object: nil)
}
// iOS 9 이상이 아닐 경우에는 removeObserver를 해줘야 함
deinit {
NotificationCetner.default.removeObserver(self)
}
@objc func notificationReceived(notification: Notification) {
// Notification에 담겨진 object와 userInfo를 얻어 처리 가능
guard let notificationObject = notification.object as? UIButton else { return }
print(notificationObject.titleLabel?.text ?? "Text is Empty")
guard let notificationUserInfo = notification.userInfo as? [String: UIColor],
let postViewBackgroundColor = notificationUserInfo["backgroundColor"] else { return }
print(postViewBackgroundColor)
}
}
장점
많은 줄의 코드
가 필요없이 쉽게 구현 가능합니다.
다수의 객체
들에 동시에 이벤트를 전달할 수 있습니다.
Notoification
과 관련된 정보를 Any?
타입의 object
,
[AnyHashable: Any]?
타입의 userInfo
로 전달 할 수 있습니다.
단점
key
값으로 Notification
의 이름과 userInfo
를 서로 맞추기 때문에 컴파일 시 구독이 잘 되고 있는지
, 올바르게 userInfo
의 value
를 받아오는지 확인이 불가능합니다.
Notification
의 post
이후 그에 대한 응답 정보를 받을 수 없습니다.
Delegation 패턴 은 각각의 객체가 delegate 를 설정하여 이벤트에 대한 처리를 합니다.
먼저, Notification
, Delegation
패턴으로 많은 객체들 에 이벤트를 전달해야 하는 경우를 생각해 봅시다.
Notification
의 경우, 특정 키 값
을 가진 notification
이 하나의 이벤트를 post
하게 되면 해당하는 키 값을 가진 notification 을 구독
하고 있는 모두에게 이벤트를 전달 하게 됩니다.
Delegation
의 경우, 이벤트를 전달받아야 하는 각각의 객체들
에 delegate
를 설정 해줘야 합니다.
명확한 답은 없지만, 많은 객체들 에 이벤트를 전달 해야 하는 경우, Notification
을 사용하고 그 외에는 코드의 흐름을 이해하기 쉽고 추적이 쉬운 Delegate
를 사용하는게 좋을 것 같습니다.