NotificationCenter와 Notification은 앱 내의 다양한 컴포넌트 간 통신을 가능하게 해주는 유용한 도구라고 한다. 전에 알아보았던 KVO와 비슷하면서 다른것 같은데 한번 알아보도록 하자.
Notification Center를 통해 등록된 관찰자에 정보를 발송하는 컨테이너 객체로 즉, 방송되는 노티피케이션의 내용을 포장하는 역할이라고 생각하면 된다.
노티피케이션 유형을 식별하기 위한 name을 관찰자를 등록할때 and Notification을 발송 할 때 직접 정의하는것도 가능하지만 extention에 미리 등록하는것이 안전하고 편리하다.
extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}
Notification Center는 Observer 패턴의 구현체로, 특정 이벤트나 정보를 방송하고 그것을 수신한다. 이를 통해 앱의 다양한 부분이 서로 독립적으로 작동하면서도 필요한 정보나 이벤트 공유가 가능하다.
func addObserver(
forName name: NSNotification.Name?,
object obj: Any?,
queue: OperationQueue?,
using block: @escaping @Sendable (Notification) -> Void
) -> NSObjectProtocol
: NotificationCenter에 새로운 관찰자 등록, 주어진 블록으로 Notification을 수신
addObserver(forName:object:queue:using:) 메서드를 사용하여 관찰자를 등록하면, 이 메서드는 NSObjectProtocol 타입의 값을 반환한다. 이 반환된 값은 "토큰"으로 간주되며, 나중에 해당 관찰자를 NotificationCenter에서 제거할 때 사용 가능하다.
func addObserver(
_ observer: Any,
selector aSelector: Selector,
name aName: NSNotification.Name?,
object anObject: Any?
)
: NotificationCenter에 새로운 괄찰자 등록. Notification을 수신할 때 주어진 선택자
func removeObserver(
_ observer: Any,
name aName: NSNotification.Name?,
object anObject: Any?
)
: NotificationCenter의 매개변수 조건과 일치하는 관찰자 항목을 제거한다.
func removeObserver(_ observer: Any)
: NotificationCenter의 발송 테이블에서 지정된 모든 관찰자항목 제거
func post(_ notification: Notification)
: 주어진 노티피케이션을 NotificationCenter에 발송, 이미 생성된 Notification객체를 직접 전달
func post(
name aName: NSNotification.Name,
object anObject: Any?,
userInfo aUserInfo: [AnyHashable : Any]? = nil
)
: 주어진 이름, 발송자, 추가 정보로 Notification을 생성한 후 전달, 이 메서드는 Notification 생성과 NotificationCenter 발송을 한번에 처리, UserInfo를 사용하여 관련된 데이터 추가 전달 가능.
: 주어진 이름과 발송자로 Notification 생성 후 발송, post(name:object:userInfo:)와 유사하지만 추가정보 없이 생성하고 전달
extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}
class ObserverClass {
init() {
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification(_:)), name: .myNotification, object: nil)
}
@objc func handleNotification(_ notification: Notification) {
print("노티피케이션 발송!")
if let data = notification.userInfo as? [String: String] {
for (key, value) in data {
print("\(key) : \(value)")
}
}
}
deinit {
NotificationCenter.default.removeObserver(self, name: .myNotification, object: nil)
}
}
class PostingClass {
func sendNotification() {
NotificationCenter.default.post(name: .myNotification, object: nil, userInfo: ["Key": "Value"])
}
}
let observer = ObserverClass()
let poster = PostingClass()
poster.sendNotification()
// 출력:
// 노티피케이션 발송!
// Key : Value
이 둘은 객체 간의 통신을 위해 사용된다는 공통점이 있다. 이 둘은 상황에 따라 적절하게 선택해야 하며, 가끔은 함께 사용되기도 한다.
: 객체 간 느슨한 결합으로 이벤트를 전달하는 기능을 제공한다. 객체를 관찰자로 등록하면 해당 이벤트가 발생했을 때 등록된 관찰자 객체에 알림을 전달한다.
둘 다 객체 간의 통신을 위해 사용되지만, 상황과 방식에 차이가 있다.
NotificationCenter는 서로 다른 로직을 담당하는 객체들 사이에서 낮은 결합도로 정보나 이벤트를 효과적으로 전달할 수 있는 유용한 도구인듯 하다. 하지만 오히려 코드가 복잡해질 수 있고 흐름을 파악하기 어려워 질 수 도 있기 때문에 무분별하게 사용하지 않는것이 정말 중요하다고 느껴진다. 또한 KVO의 주의점과 마찬가지로 잘못 사용하면 예기치 못한 오류나 메모리 누수를 초래할 수 있다고 하니 주의하도록 하자.