Notification
- 서로 다른 객체간 데이터 전달이 가능하게 해줍니다.
- Notification Center라는 싱글턴 객체를 통해 Event발생을 옵저버를 등록한 객체들에게 Notification을 post하는 방식으로 사용됩니다.
예시를 봅시다.
이 VC는 화면 전달을 받을 ViewControler 입니다.
// 데이터 전달을 받을 ViewController
class RootViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// view가 로드되자 마자 ViewController를 생성해 화면 전환을 한다.
guard let viewController = storyboard?.instantiateViewController(withIdentifier: "ViewController") else { return }
self.navigationController?.pushViewController(viewController, animated: true)
// Notification Center에 Observer를 등록한다. 등록 시 데이터 전달로 활용될 selector함수를 전달하면 해당 함수로 Notification이 전달된다. 이름은 Notification Center에 post로 등록한 이름과 같아야 한다.
NotificationCenter.default.addObserver(self, selector: #selector(notificationReceive), name: Notification.Name("noti"), object: nil)
}
// iOS 9 이상이 아닐 경우에는 removeObserver를 해줘야 합니다.
deinit {
NotificationCetner.default.removeObserver(self)
}
// 다음 화면에서 Notification이 도착하면 해당 함수의 파라미터로 전달된다.
@objc func notificationReceive(notification: Notification) {
// 어떤 뷰컨트롤러가 출력중인지 확인하기위해 자신(RootViewController)을 출력하고,
// Notification으로 전달된 값들을 출력합니다.
print("\(self)")
guard let object = notification.object as? UIButton else { return }
print(object.frame)
guard let notificationInfo = notification.userInfo as? [String: String] else { return }
print(notificationInfo)
}
}
데이터를 전달 할(push된) ViewController입니다.
class ViewController: UIViewController {
@IBOutlet weak var postNotificationButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
// postNotificationButton이 Tap되면 NotificationCenter로 post를 전달합니다.
@IBAction func postNotificationButtonTap(_ sender: UIButton) {
guard let title = sender.titleLabel?.text else { return }
// Notification의 이름은 noti, 전달할 Object는 postNotificationButton, 전달할 userInfo는 키, 값 쌍으로 사용자가 지정하면 됩니다.
NotificationCenter.default.post(name: Notification.Name("noti"), object: postNotificationButton, userInfo: ["title" : title])
}
}
RootViewController에서 ViewController가 push되어 button을 클릭하면 다음과같이 출력됩니다.
화면엔 ViewController가 띄워져 있지만 RootViewController에서 지정한 동작들을 수행하고 있는걸 확인할 수 있습니다.
작동 방식을 그림으로 그려보면 다음과 같습니다.
1. 하나의 객체에서 Event가 발생한 것을 Notification Center로 보냅니다.
2. NotificationCenter에서 발생된 Event를 등록된 옵저버에게 전달하므로 Multicast방식입니다.
유용하게 사용되는 경우는 다음과 같습니다.
- 한 화면의 이벤트에대해 다양한 다수의 수신자가 있는 경우
- 화면간 연결관계가 없는 경우
- 바로 다음 화면이 아닌 건너 건너 depth가 깊은경우
depth가 깊은 경우, delegate로 전달하려면 복잡해지기 때문입니다.
하지만 NotificationName을 직접 하나하나 확인해야하는 단점.
userInfo를 직접 타입캐스팅을 해야하므로 주의 깊게 사용해야 한다는 단점
등이 존재합니다.
** 참고
// iOS 9 이상이 아닐 경우에는 removeObserver를 해줘야 합니다.
deinit {
NotificationCetner.default.removeObserver(self)
}