노티피케이션을 보내는 방법으로
등록된 observer들에게 정보를 전달하는 것이다.
class NotificationCenter : NSObject
다른 객체의 상태가 변경될때마다 어떠한 행동을 하고 싶을 때 사용한다.
노티피케이션 센터는 디자인 패턴 중에서 옵져버 패턴 중 하나이다.
옵져버 패턴에는 KVO, Property Observer 등이 있다. 옵져버 패턴은 ViewController에 Observer가 있고, Model에 Publisher가 있는 MVC패턴에서 사용가능하다.
이를 통해 Model은 ViewController의 타입이 무엇인지에 대해 알 필요 없이 자기 상태가 변경될때마다 그것을 전달해주기만 하면 되어서 서로의 의존성을 떨어뜨릴 수 있다. 또한, 여러개의 ViewController가 하나의 Model의 변경사항을 사용가능하다.
관찰 중인 객체에서 발생하는 이벤트를 여러 다른 객체에 알리는 메커니즘을 정의할 수 있는 디자인 패턴이다.
그럼 이제 NotificationCenter을 사용하려면 어떻게 해야하는지 알아보자.
NotificationCenter = .default
: 방송국 선언Notification.Name("방송이름")
: 방송 선언NotificationCenter.post(name: 2번, object: nil)
: post 보낼 함수 안에 선언NotificationCenter.addObserver(self, selector: #selector(5번), name: 2번, object: nil)
: post 받을 타입 안에 선언@objc
: post 받고나서 실행할 함수에 선언처음엔 코드가 이곳 저곳 흩어져있어서 정말 헷갈렸지만 작동 방법을 이해하고 나서는 이해가 쉬워졌다.
방송국을 먼저 선언하고, (NotificationCenter은 싱글턴으로 정의되어 있어서 타입 프로퍼티인 .default 를 이용하여 인스턴스를 가져온다.)
그리고 나서 어떤 방송을 할지 결정하여 방송 이름을 선언한다. 이 방송 이름을 post함수 안에 매개변수로 전달한다.
post함수는 어떤 일이 실행되면 실행됐다는 정보를 보내는 함수이다.
이 함수가 보낸 정보를 받기 위해서 받는 쪽은 observer 등록을 해야한다.
post를 받을 타입안에 addObserver을 선언하고, 방송이름을 매개변수로 전달해주는 동시에 방송을 받고나서 실행할 함수도 전달한다.
방송을 받고나서 실행할 함수 앞에는 @objc를 붙여서 컴파일러가 잘 찾아갈 수 있도록 명시해준다.
예제 코드
import UIKit
//1st 어떤 방송을 보낼지
let didPressButton: Notification.Name = Notification.Name("버튼누름")
let notificationCenter: NotificationCenter = .default
// Model
// 정보가 바뀌지 않으니 구조체가 나음 (클래스보다)
struct Registrant {
let name: String
let phoneNumber: String
}
class ViewController: UIViewController {
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var phoneNumberTextField: UITextField!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var phoneNumberLabel: UILabel!
// Model
var registrantList: [Registrant] = []
override func viewDidLoad() {
super.viewDidLoad()
//구독신청 4???
notificationCenter.addObserver(self,
selector: #selector(showInfo), //[name]방송을 들으면 [selector]를 실행하겠다!
name: didPressButton,
object: nil)
}
//controller
@IBAction func hitRegisterButton(_ sender: Any) {
register()
//view
nameTextField.text = ""
phoneNumberTextField.text = ""
}
@IBAction func hitCheckButton(_ sender: Any) {
}
@objc
func showInfo() {
//방송을 듣고나서 해야할 일 3
let currentIndex = registrantList.count - 1
nameLabel.text = registrantList[currentIndex].name
phoneNumberLabel.text = registrantList[currentIndex].phoneNumber
}
func register() {
guard let nameText = nameTextField.text else {
return
}
guard let phoneNumberText = phoneNumberTextField.text else {
return
}
let personalInfo = Registrant(name: nameText, phoneNumber: phoneNumberText)
registrantList.append(personalInfo)
// 배열에 연락처 추가한 후에 방송해달라고 방송국에게 요청 2
notificationCenter.post(name: didPressButton, object: nil)
}
}