[TIL] NotificationCenter

valse·2022년 8월 19일
0

iOSInterViewController

목록 보기
1/8
post-thumbnail

NotificationCenter 객체

한국어로 번역하면 알림기지국.

앱 내의 각각에서 발생하는 여러 이벤트들이 있다.
화면의 캡쳐가 일어난다던가, 특정 값이 변한다던가, 어떤 뷰가 불러와진다던가 등등 수도 없이 많은 활동이
앱 내에서는 늘 일어나고 있다.

이 이벤트들의 상호작용이 원활하게 일어나도록 선을 이어줄 수 있는데, 이 연관성을 NotificationCenter로 확보할 수 있다.
사실 특정 상황에서는 Delegate 패턴을 쓰는 것이 더 낫지만 NotificationCenter를 써야 하는 이유는 아래와 같다.
해당 내용은 해외 블로거의 글에서 발췌했다.

  1. 하나의 클래스에서 여러 클래스로의 전파가 가능함
  2. 여러 클래스에서의 전파를 하나의 통로로 수신할 수 있음

기본으로 제공되는 default 싱글톤 객체가 있으며, 2가지 형태의 addObserver() 메소드를 활용하거나, post()로 게시 활동을 받아올 수 있다.
이 싱글톤 객체를 쓰고 싶지 않다면 커스텀도 가능하다.

removeObserver()를 제공하지만, 꼭 필수적으로 개발자가 구현할 필요는 없다고 한다.

이 객체 활동으로 리턴되는 비동기 시퀀스와 Combine 퍼블리셔를 받아올 수도 있다.
각각 NotificationCenternotifications, publisher 메소드를 호출하여 활용한다.

그러나 NotificationCenter는 하나의 프로그램 내에서만 작동하기 때문에 다른 프로세스와 노티피케이션을 주고받고 싶다면 DistributedNOtificationCenter를 써야 한다.


활용

기본 형태 활용을 잘 익혀보도록 하자.

우선 싱글톤 객체를 만들어보자.
텍스트가 텍스트필드 위에 없을 때는 placeholder를 노출시키고 그 외의 경우엔 숨겨줄 것이다.
UIView 내의 UITextView에서 텍스트 변화가 일어나는 상황이다.
특정 텍스트가 변화할 때마다 셀렉터 함수가 호출될 것이고,
UITextView의 특정 텍스트가 변화할 때를 받아와야 하니까 name 파라미터에는 UItextView.textDidChangeNotification 을 전달한다.

// MARK: UIView
func setNotification() {
		NotificationCenter.default.addObserver(self,
        selector: #selector(textInputDidChange),
        name: UITextView.textDidChangeNotification,
        object: nil)
}

// MARK: Selectors
@objc func textInputDidChange() {
	placeholderLabel.isHidden = !self.messageInputTextView.text.isEmpty
}

이런 식으로 앱 내의 정보 변화, 이벤트 등등을 감지해서 쉽게 뷰를 새로 그릴 수 있다.
이를 활용하면 동적 UI도 그릴 수 있다.
UIResponder 객체는 앱 내의 이벤트가 서로 상호작용할 수 있도록 기본 구조를 갖추고 있는데, 키보드의 움직임음 받아오거나, 텍스트의 변화를 감지할 수도 있다.
모든 UIView 객체를 포함하여 UIViewController까지 Responder가 될 수 있다.
UIResponder 는 이번 게시글의 주인공이 아니라 이만 줄이고, 추가 내용이 필요하다면 공식 문서를 보자.
정말 정리가 잘 되어 있다!

다시 원점으로 돌아오자.
이번엔 NotificationCenter를 활용해서 키보드가 화면에 등장하면 뷰의 상단을 끌어 올리고, 키보드가 사라지면 다시 원 상태로 돌려보자.

// MARK: UIView
func setNotification() {
		NotificationCenter.default.addObserver(self,
        selector: #selector(keyboardWillShow),
        name: UIResponder.keyboardWillShowNotification,
        object: nil)
        
		NotificationCenter.default.addObserver(self,
        selector: #selector(keyboardWillHide),
        name: UIResponder.keyboardWillHideNotification,
        object: nil)
}

// MARK: Selectors
@objc func keyboardWillShow() {
	if view.frame.origin.y == 0 {
		self.view.frame.origin.y -= 60
	}
}
	
@objc func keyboardWillHide() {
	if view.frame.origin.y != 0 {
		self.view.frame.origin.y = 0
	}
}

그런데 이렇게만 쓰면 NotificationCenter의 절반만 활용하는 것이라 할 수 있다.
기본 이벤트만 Receiverobserver로 쓰고 있고, broadcaster를 직접 쓰고 있지 않기 때문이다.
post 를 써서 Name에 해당하는 옵저버들을 활성화하는 것이 NotificationCenter의 핵심이다.
여러 객체 간의 이벤트와 호출해야 하는 메소드 통신이 가능해지고, 심지어 데이터도 전달할 수 있다! 무려 여러 객체로!

// MARK: Broadcaster
func userLogin() {
	// code
    let loginInfo = ["name": "길동이", "age": "15"]
    NotificationCenter.default.post(name: .loginSuccess, object: loginInfo)
}

// MARK: Receiver
func setupNotification() {
	NotificationCenter.default.addObserver(self,
        selector: #selector(loggedIn(_:)),
        name: .loginSuccess,
        object: nil)
}

// MARK: Selector
// NotificationCenter로 전달되는 데이터는 Notification 구조체 형태로 전달된다.
@objc func loggedIn(_ notification: Notification) {
	print(notification.object as? [String: Any] ?? ["데이터가": "없는디?"])
}

정리

간단하게 NotificationCenter의 목적과 쓰임, 활용을 요약.

  1. NotificationCenter는 델리게이트 패턴의 1:1 대응을 앱 전체로 확장하고 데이터를 전달하기 위해 활용할 수 있다.
  2. 앱 내에서 특정 이벤트가 발생하면 정의된 메소드를 호출하거나 행동한다.
  3. 기본으로 제공해주는 싱글톤 객체가 있으며 커스터마이징이 가능하다.
  4. addObserver 메소드를 활용하여 이벤트가 감지될 때마다 특정 메소드를 호출할 수 있다.
  5. post 메소드를 활용하여 내가 원하는 곳에서 노티피케이션의 트리거를 정의하고 데이터를 전달할 수 있다.
  6. 간단하게는 뷰의 특정 요소나 이벤트를 감지하여 동적 UI를 구현할 수 있고, 비동기 작업의 결과를 여러 객체로 동시에 전파하는 방식으로 활용할 수 있다.

참고 자료들

애플공식문서 - NotificationCenter
NotificationCenter in Swift <- 일독 강력 추천
Is necessary removeObserver in NSNotificationCenter for iOS 9.0 and later or macOS 10.11 and later ?

220819

profile
🦶🏻🦉(발새 아님)

0개의 댓글