IOS 개발일지

Notification Center - Publisher

호종이 2022. 5. 24. 22:45
 

Notification Center - 옵저버 등록과 제거

var observer: NSObjectProtocol? observer = NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: nil) { notification in print("user tak..

forstudy.tistory.com

 

Notification Center - publisher 


Notification Center 에 addObserver 를 통해 notification 을 수신했을 때 실행할 클로저를 정의할 수도 있지만, Notification 을 발행하는 Combine publisher 형태로  제공받아 Combine 프레임워크의 강력한 operation 을 적용할 수도 있다. 

func publisher(for name: Notification.Name, object: AnyObject? = nil)
	-> NotificationCenter.Publisher

name

publish 할 Notification 의 이름

object

위 name 을 가지는 Notification 을 post 할 object, 만약 nil 이면, 해당 이름을 가지는 모든 노티피케이션을 sender 에 상관없이 publish 한다.

 

Return Value

Notification 을 publish 하는 Publisher 를 리턴한다.

 

Notification Publisher 예시


UITextField 는 기본적으로 text 프로퍼티가 바뀔 때마다, UITextField.textDidChangeNotification 을 post 한다. 즉 Notification Center 를 통해 해당 텍스트 변경 이벤트를 구독하는 옵저버를 만들거나, 텍스트 변경 이벤트를 publish 하는 publisher 를 사용할 수 있다. 

위와 같은 화면이 있을 때, textField 의 값이 바뀔 때마다 Label 의 text 가 똑같이 변경되는 코드를 작성해보자. 

 

Step 1. text 변경 이벤트를 발행하는 publisher 생성하기

extension UITextField {
  func textPublisher() -> AnyPublisher<String, Never> {
    NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: self)
      .compactMap {
        $0.object as? UITextField
      }
      .compactMap(\.text)
      .eraseToAnyPublisher()
  }
}
  • UITextField extension 을 통해, 각 UITextField 의 text 가 변경될 때 해당 변경 이벤트를 publish 하는 publisher 를 반환하는 함수를 정의하였다
  • compactMap -> 하위 stream 에 nil 이 아닌 요소만 publish 하고, nil 인 요소는 제공하는 combine operator
  • Notification sender 를 UITextField 로 타입 캐스팅하고, 해당 UITextField 의 text 프로퍼티를 publish 한다.

Step 2. Notification Publisher 를 통해 받는 값을 Label 에 적용하기

class ViewController: UIViewController {
  
  private var cancelBag: Set<AnyCancellable> = []
  @IBOutlet weak var label: UILabel!
  @IBOutlet weak var textField: UITextField!

  override func viewDidLoad() {
    super.viewDidLoad()
    addTextFieldChangeObserver()
  }

  private func addTextFieldChangeObserver() {
    // 텍스트 필드 변경 이벤트를 Label 의 text 프로퍼티에 할당
    textField.textPublisher()
      .receive(on: DispatchQueue.main)
      .assign(to: \.text!, on: label)
      .store(in: &cancelBag)
  }
}
  • textField 가 변경될 때마다, 해당 변경된 값을 UILabel 의 text 프로퍼티로 할당함

 

위와 같이 Notification Center 와 Combine 을 같이 사용하면 아래와 같은 결과를 얻을 수 있다.