지난번에 delegate에 대해 공부한 것에 이어서!
오늘은 NotificationCenter
에 대해 알아보자.
지난 글 안 본 사람은 보고 오삼요.
[iOS] 데이터 전달하기(1) - Delegate
먼저 애플 공식 문서를 보자!
등록된 관찰자에게 정보를 브로드캐스트할 수 있도록 하는 알림 디스패치 메커니즘입니다.
설명을 봐도 뭔 소리인지 이해가 잘 가지 않는다면.. 유튜브를 떠올려보자.
어떤 영상을 보다보니 유튜버 A가 너무 재미있어서 구독을 했다. 이후 A가 영상을 업로드 하면, A를 구독하고 있는 구독자 B, C, D, ... 에게 알림이 울린다.
자, 여기서 유튜브가 바로 NotificationCenter
이다.
NotificationCenter는 어떤 객체로부터 어떤 이벤트를 받아 자신을 구독하고 있는 객체들에게 알림을 보내준다.
즉, 앱 내에서 메시지를 던지면 아무데서나 메시지를 받을 수 있도록 한다.
NotificationCenter는 싱글톤으로 구성되어 있는데, 덕분에 사용자가 인스턴스를 만들지 않아도 사용할 수 있다.
코드로 살펴보기 전에! 먼저 용어 정리부터 하자.
어떤 객체로부터 어떤 이벤트를 받아 자신을 구독하고 있는 객체들에게 알림을 보내준다.
싱글톤으로 구성되어 있어, 사용자가 인스턴스를 만들지 않아도 사용할 수 있다.
NotificationCenter에 자신의 정보를 등록하여 알림을 받고자 하는 객체를 의미한다. 즉, 앞선 예시의 구독자
라고 할 수 있다.
모든 객체는 observer가 될 수도 있고, 이벤트를 보내는 객체가 될 수도 있다.
post는 객체가 NotificationCenter로 이벤트를 보내는 행위이다. 즉, 구독자가 유튜버를 구독하면 알림이 오는 그 자체를 의미한다.
Post가 이벤트를 보내는 행위 그 자체라면, Notification은 그 이벤트에 해당한다.
즉, 유튜버 A의 영상 업로드 알림을 의미한다.
자, 만약 한 앱에서 주고 받고자 하는 알림이 여러 개라면 어떻게 구분할까?
바로 각각의 Notification에 이름을 붙여 식별하면 된다!
이제 직접 사용해보자.
먼저, 유튜브를 구독한 구독자들에게 알람을 보내는 방법이다.
함수 원형은 다음과 같다.
func post(
name aName: NSNotification.Name,
object anObject: Any?
userInfo aUserInfo: [AnyHashable : Any]? = nil
)
여기서 object와 UserInfo가 뭐냐면...
object에는 notification 발신자의 객체를 담는다.
뭐하러 담냐구요??
바로 notification을 받는 수신자들 중에서 특정 일부에게만 보내기 위함이다!
이러한 경우에 발신자 즉, 유튜버 A라는 정보를 이벤트에 담으므로써 구독자 C가 유튜버 A의 알림만을 받을 수 있도록 한다.
이처럼, 특정한 객체에게만 알림을 보내도록하기 위해서는 object에 발신자 객체를 담으면 된다.
하지만 귀찮으면 그냥 주고받을 데이터를 넣어도...
원칙은 안대요!!
userInfo에는 notification을 발신할 때 함께 전달하고자 하는 데이터를 담는다.
전달하고자 하는 데이터는 딕셔너리로 구성한다.
유튜버 A의 영상 업로드 알림을 보낸다면, 영상의 제목과 설명도 같이 보내야 한다.
제목과 설명 데이터를 userInfo에 담아서 발신하자!
이제 영상 알림을 받을 구독자를 설정하자.
함수 원형은 다음과 같다.
func addObserver(
_ observer: Any,
selector aSelector: Selector,
name aName: NSNotification.Name?,
object anObject: Any?
)
selector는 notification을 받은 뒤, 수신한 객체가 해야할 일을 담은 함수이다.
obj-C 형태로 해야할 작업을 함수로 구현한다.
아까 앞에서 설명한 그 object와 동일한 파라미터이다.
자신이 수신하고자 하는 발신자의 notification만을 받을 수 있도록 한다.
object에 유튜버 A 객체를 담아두면, 어떤 notification이 왔을 때 발신자가 유튜버 A라면 수신해서 핸드폰에 알람이 울릴 것이다.
만약 아니라면, 그냥 무시한다. ^^
override func viewDidLoad() {
...
NotificationCenter.default.addObserver(
self,
selector: #selector(editDiaryNotification(_:)),
name: NSNotification.Name("editDiary"),
object: nil
)
}
@objc func editDiaryNotification(_ notification: Notification) {
// 전달한 객체 받아오기!!
guard let diary = notification.object as? Diary else { return }
...
}
NotificationCenter.default.post(
name: NSNotification.Name("editDiary"),
object: diary,
userInfo: nil
)
원래는 object에 발신자 객체를 담는 목적으로 사용해야지, 전달의 목적으로 쓰면 안됨!!
사실 딕셔너리로 구성하기 귀찮았슴..
전에 공부한 delegete보다 사용하기는 더 쉬운 것 같다. 그래도 Notification을 남용하면 메모리를 많이 잡아먹는다고 한다.
그러니까 적당히 쓰자 !!