iOS

Swift의 우체국 NotificationCenter

흐성진 2024. 4. 10. 01:08
반응형

Intro

들어가기 앞서 저는 NotificationCenter를 우체국이라고 가정하고 들어갈게요.

우리가 편지를 우체통에 넣으면 어떻게 될까요?

그 과정에 NotificationCenter 와 매우 흡사합니다.

 

What is NotificationCenter?

NotificationCenter

  1. addObserver : 우체부는 우체국에게 '제가 00동으로 가는 우체부입니다'라고 등록을 합니다.
  2. Something Happen : 서울의 황성진은 고향의 친구에게 보낼 편지를 썼습니다.
  3. post : 황성진은 우체국에 편지를 부쳤습니다.
  4. notify : 우체국은 00동에 가는 우체부에게 편지가 왔다고 전달해줍니다.
  5. selector : 우체부가 고향의 친구에게 갈 편지를 배송해줍니다.

기본적인 NotificationCenter 이 작동하는 방식이다.

더 자세히 NotificationCenter 에 대해서 자세히 알아보기전에 사용되는 용어가 여러가지가 있는데 우선 용어 정리부터 해보자.

NotificationCenter(우체국)

  • NotificationCenter는 객체로부터 어떤 이벤트를 받아 자신에게 등록된 객체들에게 알림을 보내주는 객체입니다. NotificationCenter는 싱글톤으로 구성되어 있어 사용자가 인스턴스를 만들지 않고 NotificationCenter를 부를 수 있습니다.

Observer

  • NotificationCenter의 Observer는 NotificationCenter에 자신의 정보를 등록하여 알림을 받고자 하는 객체를 의미합니다. 모든 객체는 Observer가 될 수도 있고, 이벤트를 보내는 객체가 될 수도 있습니다.

Post

  • Post는 객체가 NotificationCenter로 이벤트를 보내는 행위를 의미합니다.

Notification

  • Notification은 이벤트를 발행하는 객체가 NotificationCenter에 보내는 이벤트를 의미합니다

NotificationName

  • NotificationCenter는 싱글톤이라고 했었죠? 그럼 이벤트를 여러 개 만들고 싶을 때는 어떻게 할까요? 예를 들어, 색상을 바꾸는 알림, 선 두께를 바꾸는 알림을 보내고자 한다면, 싱글톤인 NotificaionCenter는 자신에게 보내지는 이벤트가 어떤 이벤트인지 알고 있어야 합니다. 그래서 이벤트를 보내는 객체는 NotificationName이라는 식별자를 NotificationCenter에 알려주어서 이를 구분할 수 있게 합니다.

 

언제 사용하는게 좋을까?

  • 앱 내에서 공식적인 연결이 없는 두 개 이상의 컴포넌트들이 상호작용이 필요할 때
  • 상호작용이 반복적으로 그리고 지속적으로 이루어져야 할 때
  • 일대다 또는 다대다 통신을 사용하는 경우

구현해보기

Notification Center로 Post 하기

    func notificate(writeText: String) {
        NotificationCenter.default.post(name: Notification.Name("writeText"), object: nil, userInfo: ["myWriting": writeText])
    }
  • name : 전달하고자 하는 notification의 이름 (이걸 통해 알림을 식별)
  • object : addObserver의 object 부분과 목적이 동일한데, 특정 sender의 notification만 받고 싶은 경우 작성 해주면 된다. filter 기능과 같다고 생각하면 될 것 같다. 없으면 nil
  • userInfo : notification과 관련된 값이다. extra data를 보내는데 사용한다.

 

Notification Center에 Observer 등록하기

  • notification을 observe 해주기 전에 Notification Center에 addObserver 과정을 무조건 먼저 해주어야 한다.
  • addObserver가 있으면 removeObserver도 있는데 방식은 같다.
// Notification Name 설정
 NotificationCenter.default.addObserver(self, selector: #selector(receiveNoti), name: Notification.Name("writeText"), object: nil)

 

Observer가 실행할 함수 만들기

 @objc func receiveNoti(notification: Notification) {
        guard let writeText = notification.userInfo?["myWriting"] as? String else { return }
        showField.text = writeText
}

 

Observer 제거하기

NotificationCenter.default.removeObserver(self)

전체코드

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var writeField: UITextField!
    @IBOutlet weak var showField: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    func notificate(writeText: String) {
        NotificationCenter.default.post(name: Notification.Name("writeText"), object: nil, userInfo: ["myWriting": writeText])
    }

    @objc func receiveNoti(notification: Notification) {
        guard let writeText = notification.userInfo?["myWriting"] as? String else { return }
        showField.text = writeText
    }

    @IBAction func sendButtonTapped(_ sender: UIButton) {
        NotificationCenter.default.addObserver(self, selector: #selector(receiveNoti), name: Notification.Name("writeText"), object: nil)
        guard let writeText = writeField.text else { return }
        notificate(writeText: writeText)
        NotificationCenter.default.removeObserver(self)
    }

}

 

NotificationCenter 활용 시 고려해야 할 사항

  • Observer 제거의 중요성: Observer를 제거하는 시점에 대해 좀 더 명확히 설명하는 것이 좋습니다. 예를 들어, deinit에서 Observer를 제거하는 것이 일반적인 관례입니다. 이는 메모리 누수를 방지하고, 이미 메모리에서 해제된 객체에 알림이 전송되는 것을 방지하기 위함입니다.

 

  • Thread Safety: NotificationCenter는 기본적으로 동기적으로 동작하며, 알림을 보낸 스레드와 동일한 스레드에서 Observer의 액션을 실행합니다. 따라서, UI 업데이트와 같이 메인 스레드에서 실행되어야 하는 작업이 있다면, 적절한 스레드에서 실행되도록 관리해야 합니다. 이는 DispatchQueue.main.async를 사용하여 관리할 수 있습니다.

 

  • Notification의 Payload 다루기: userInfo 딕셔너리를 통해 전달되는 데이터를 안전하게 다루는 방법에 대해 더 깊이 다룰 수 있습니다. 예를 들어, 데이터 타입을 확인하고 옵셔널을 안전하게 언래핑하는 방법 등입니다.

 

  • Performance Considerations: 많은 수의 Observer가 동일한 Notification에 대해 등록되어 있을 때, 각 Notification의 처리 시간이 앱의 성능에 영향을 줄 수 있습니다. 따라서, NotificationCenter를 사용할 때는 성능에 미치는 영향도 고려해야 합니다.

 

정리

NotificationCenter는 iOS 앱에서 컴포넌트 간의 결합도를 낮추면서도 효과적으로 데이터를 전달하고 이벤트를 처리할 수 있는 강력한 도구입니다. 그러나 이를 사용할 때는 메모리 관리, 성능, 스레드 안전성 등을 주의 깊게 고려해야 합니다. 또한, NotificationCenter의 사용은 필요한 경우에 한해 최소화하여 앱의 유지보수성과 성능을 극대화하는 것이 좋습니다.

 

참고

[iOS/Swift] Notification, NotificationCenter

Swift NotificationCenter 구현

반응형