iOS 환경에서 Observer 패턴을 사용하는 NotificationCenter와 Notification 객체에 대해 알아봅니다.
model의 변화에 따라 view를 update하기 위한 패턴으로,
Notification은 나중에 실행될 closure를 작성하는 것으로 볼 수 있습니다.
A container for information broadcast through a notification center to all registered observers.
Notification center를 통해 observer에게 전달할 정보를 담은 컨테이너로
구조체이며, 아래와 같은 프로퍼티를 가지고 있습니다.
// struct Notification
var name: Notification.Name // 알림을 식별하는 태그
// An object that the poster wishes to send to observers.
var object: Any? // 옵저버에게 보내고 싶은 객체, 주로 poster 객체
var userInfo: [AnyHashable: Any]? // notification 발생 시 필요한 정보들을 전달할 수 있다.
Notification을 전달하는 classNotification을 발송하면 전달 받을 observer의 처리가 끝날 때까지 대기 — synchronous 방식NotificationCenter.default로 공유합니다.// class NotificationCenter
// observer 등록
func addObserver(forName: Notification.Name,
object: Any?, // poster, or nil for "anyone"
queue: OperationQueue?,
using block: @escaping (Notification) -> Void) -> NSObjectProtocol? // closure executed when notification post
// observer 제거
func removeObserver(_ observer: Any?,
name aName: NSNotification.Name
object anObject: Any?)
// Notification 발송
func post(name aName: NSNotification.Name,
object anObject: Any?, // who is sending this notification (usually self)
userInfo aUserInfo: [AnyHashable: Any]? = nil) // any info you want to pass to station listeners
custom Notification.Name을 만들 때는 extension 하는 것이 권장됩니다.
일반적으로 뷰가 화면에 떠있을 때 알림을 받아야 하므로, 뷰가 화면에서 사라졌을 때 observer를 제거해주는 것이 memory resource 낭비를 줄일 수 있다. 따라서 viewDidAppear, viewWillAppear에서 observer를 추가하고 viewDidDisappear, viewWillDisappear에서 observer를 제거한다.
var observer: NSObjectProtocol? // a cookie to later 'stop listening' with
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
observer = NotificationCenter.default.addObserver(forName: Notification.Name.AVPlayerItemDidPlayToEndTime,
object: nil,
queue: .main,
using: { [weak self] _ in
self?.playPauseButton.isSelected = false
})
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(observer)
})
👏