NotificationCenter 에 대해서 알아보자.

2023. 11. 19. 02:05Mobile/iOS

NotificationCenter 기본개념

class NotificationCenter: NSObject

A notification dispatch mechanism that enables the broadcast of information to registered observers.

등록된 관찰자에게 정보를 브로드 캐스팅할 수 있는 알림 방송  📢 메커니즘 이다. 

 

Objects(객체는)

  • addOberver(_: selector: name: object:) 또는
  • addObserver(forName: object: queue: using:) 메소드를 사용하여
  • 알림(NSNotification 객체)을 수신하기 위해 알림 센터에 등록한다.

객체가 자신을 관찰자로 추가할 때 어떤 알림을 받아야 하는지 지정한다.

따라서 객체는 여러 가지 다른 알림에 대한 관찰자로 자신을 등록하기 위해 이 메서드를 여러 번 호출 할 수 있다.

객체가 자신을 관찰자로 추가할 때 어떤 알림을 받아야 하는지 지정한다.

따라서 객체는 여러가지 다른 알림에 대한 관찰자로 자신을 등록하기 위해 이 메서드를 여러 번 호출 할 수 있다.

실행 중인 각 앱에는 기본 알림 센터가 있으며, 새로운 알림 센터를 만들어 특정 상황에서 통신을 구성할 수 있다.

알림 센터는 단일 프로그램 내에서만 알림을 전달할 수 있다. 다른 프로세스에 알림을 게시하거나 다른 프로세스로부터 알림을 받으려면 DistributedNotification 을 대신 사용한다.

동작방식

Getting the Default Notification Center

기본 알림센터 가져오기

알림 관찰자를 추가, 제거 하는 법

func addObserver(forName: NSNotification.Name?, object: Any?, queue: OperationQueue?, using: (Notification) -> Void) -> NSObjectProtocol

func addObserver(
    forName name: NSNotification.Name?,
    object obj: Any?,
    queue: OperationQueue?,
    using block: @escaping @Sendable (Notification) -> Void
) -> NSObjectProtocol

Adds an entry to the notification center to receive notifications that passed to the provided block.

→ 제공된 블록에 전달된 알림을 수신하기 위해 알림 센터에 항목을 추가한다.

Return Value ( 반환하는 값 )

An opaque object to act as the observer. Notification center strongly holds this return value until you remove the observer registration.

관찰자로서 행동하는 불투명 객체이다. NotificationCenter 는 관찰자 등록을 제거할 때까지 이 반환 값을 강력하게 보유한다.

1. 알림이 하나 이상의 관찰자 블록을 트리거하는 경우,( 그러나, 현재 스레드 또는 해당 큐에서) 블록은 모두 동시에 실행될 수 있다.

let center = NotificationCenter.default
let mainQueue = OperationQueue.main
localeChangeObserver = center.addObserver(
    forName: NSLocale.currentLocaleDidChangeNotification,
    object: nil,
    queue: mainQueue) { (note) in
        print("The user's locale changed to: \(NSLocale.current.identifier)")
    }
}

 

알림 수신을 중지하려면 관찰자를 등록 취소한다. 관찰자 등록 취소하려면 가능한 가장 구체적인 세부정보와 함께 RemoveObserver(_:) 또는 RemoveObserver(_: name: object:) 를 사용한다.

시스템이 addObserver(forName: object: queue: using:) 가 지정하는 객체의 할당을 취소하기 전에 `RemoveObserver(:)또는RemoveObserver(: name: object:)` 를 호출해야한다.

let center = NotificationCenter.default
guard let localeChangeObserver = self.localeChangeObserver else { return }
center.removeObserver(localeChangeObserver)

2. 또 다른 일반적인 방법

예제와 같이 관찰 블록 내에서 관찰자(observer)를 제거해 일회성 알림을 만드는 것이다.

let center = NotificationCenter.default
let mainQueue = OperationQueue.main
token = center.addObserver(
    forName: NSNotification.Name("OneTimeNotification"),
    object: nil,
    queue: mainQueue) {[weak self] (note) in
        print("Received the notification!")
        guard let token = self?.token else { return }
        center.removeObserver(token)
}

NOTE
유지 주기(retain cycle)를 방지하려면, 자체가 관찰자(Observer) 를 강력한 참조로 포함할 때 블록 내부의 자체에 대한 약한 참조를 사용해라.

 

예를 들어, 인스타그램 계정에 사용자가 로그인 했을 시에,  연관된 것을 보여줄 수 있도록 사용자가 사용하는 인스타계정명이나 ID 를 전달해주는 역할을 한다고 생각하면 쉬울 거 같다!  그 정보를 알림 센터에 등록해주고 addObserver 를 사용하면 추가되고, 사용자의 계정 이미지 컬렉션 뷰들 뿐만 아니라, 사용자가 팔로우 하는 사람들을 볼 수 있는 feed, 사용자와 연관된 알고리즘을 보여주는 뷰 등을 NotificationCenter 를 사용해 가져올 수 있는 것이다. 

 

 

UIKit 에서 storyboard 에 탭바 컨트롤러에 탭바 세 뷰를 만들고, 마지막 뷰에 UIButton 을 만들어 클릭 시에 배경색이 바뀌는 예제를 통해 설명을 해보자면,

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    @IBAction func buttonTapped(_ sender: UIButton) {
        NotificationCenter.default.post(name: Notification.Name("Colorchanged"), object: nil)
        view.backgroundColor = .systemTeal
    }
}

ViewController ( UIButton 이 있는 뷰컨트롤러 )

우선, NotificationCenter의 default 에 post(값 넘김) 의 name 에 Notification.Name("동일하게 넘겨줄 문자열을 지정해줘야함") 을 지정하고, 동일한 배경색이 나오도록 설정해준다.
그 다음 나머지 두 탭바뷰컨트롤러에도 그걸 전달 받을 수 있도록 해준다!

 

그게 바로 위에서 설명해준 관찰자 지정해주는 addObserver 녀석이다! 동일하게 저장된 문자열(String) 인 Colorchanged 를 가져온다. 그리고 그걸 가져오는 옵씨 셀렉터는 notificationReceived() 로 지정해주고, ViewController 에서 지정해줬던 컬러대로 똑같이 설정해준다!

import UIKit

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

         NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived), name: Notification.Name("Colorchanged"), object: nil)

    }

    @objc func notificationReceived() {
        view.backgroundColor = .systemTeal
    }
}
import UIKit

class ThirdViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived), name: Notification.Name("Colorchanged"), object: nil)
    }

    @objc func notificationReceived() {
        view.backgroundColor = .systemTeal
    }

}

 

생각해보니 이 NotificationCenter 도 UserDefault 와 비슷한 너낌적인 느낌이다. 길지 않은 시간에 조만간 UserDefault 도 한번 정리해봐야겠다.

UIButton을 누를시 나머지 탭바 뷰에도 배경색 변경하는 메소드가 전달되도록 했다.

 

 

참고

https://developer.apple.com/documentation/foundation/notificationcenter

 

- 피드백 환영합니다! 글은 자주 수정되거나 추가될 수 있습니다. 😅