NotificationCenter는 iOS에서 런타임 이벤트를 감지하고 처리하기 위한 기능이다.
프로젝트에 사용했던 위치 정보 업데이트 기능 기반으로 설명
(사용자가 지도 움직임 -> 위치정보 업데이트하여 정렬 다시)
: 특정 이벤트나 상태 변화를 나타내는 객체. 주로 이름, 객체, 사용자 정보 딕셔너리로 구성
name: 노티피케이션의 이름. 식별자 역할을 함.
object: 이벤트를 발생시킨 객체. 옵셔널.
userInfo: 추가 정보를 담은 딕셔너리. 옵셔널.
: 노티피케이션을 관리하고, 옵저버들에게 전달하는 싱글톤 객체.
addObserver: 옵저버를 등록하고, 특정 노티피케이션을 받을 메소드를 지정.
post: 노티피케이션을 발생시키고, 등록된 옵저버들에게 전달.
removeObserver: 옵저버를 제거.
전체적인 흐름
1.viewDidLoad()에 옵저버 등록, 이벤트 감지 메서드 설정
2. 이벤트 발생시NotificationCenter에 노티피케이션 전송
3.NotificationCenter는 해당 노티피케이션을 전 옵저버에 전달
4. 옵저버는 전달받은 메서드를 처리
NotificationCenter.default.addObserver(self, selector: #selector(updateLocation), name: .locationDidUpdate, object: nil)
NotificationCenter.default: 싱글톤 객체'.addObserver 메서드로 updateLocation을 옵저버로 등록하여 대기시킴.locationDidUpdate 노티피케이션 발생시 등록된 updateLocation 메서드 호출참고 - selector: obj-c와의 호환성을 위해 사용. 클로저 기반으로 바꿔서 사용할 수도 있으나, NotificationCenter 자체가 obj-c 기반이라 여전히 selector를 자주 사용. 이에 대해서는 추후 더 자세히 다룰 예정
func postLocationUpdate(location: CLLocation) {
NotificationCenter.default.post(name: .locationDidUpdate, object: nil, userInfo: ["location": location])
}
.post 메서드로 노티피케이션을 보냄object, userInfo에 들어가는 정보를 함께 노티피케이션 센터로 전달object: 특정 객체에 대해서만 노티피케이션을 받으려면 설정. 보통은 nil로 설정해서 모든 객체의 노티피케이션을 받음.object: someObject로 설정하면 someObject가 보내는 객체의 노티피케이션만 받는다.userInfo: 딕셔너리 형태로 필요한 정보를 전달, [AnyHashable: Any] 타입의 딕셔너리.NotificationCenter는 옵저버들에 .locationDidupdate 노티피케이션을 전달@objc func updateLocation(notification: Notification) {
if let location = notification.userInfo?["location"] as? CLLocation {
currentLocation = location
updateMapRegion(location: location)
updateTableViewSorting()
}
}
함수 설명
userInfo로 받아오는 딕셔너리는 [AnyHashable: Any] 타입으로, 여기서는 location 키에 해당하는 값을 가져온다.
as? 타입 변환을 이용해 딕셔너리에서 가져온 값의 타입 Any를 변환, 여기서는 CLLocation 타입의 옵셔널로 변환한다. 변환이 실패할 경우 nil을 반환.
변환이 성공, 즉 옵셔널 값이 nil이 아니면 이후 코드가 실행된다.
참고:
as?는 타입을 안전하게 변환하는 연산자. 캐스팅이 성공하면 해당 타입의 옵셔널 값을 반환하고, 실패하면 nil을 반환하기 때문에 런타임 오류를 방지할 수 있다. 옵셔널 바인딩(if let이나 guard let)과 함께 사용하면 더욱 안전하게 타입 변환을 처리할 수 있다.
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
앱이 foreground에서 사용되다가 background로 전환될 때, 혹은 반대의 경우, 필요한 작업을 수행하기 위해 NotificationCenter를 사용
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(settingsDidChange), name: UserDefaults.didChangeNotification, object: nil)
오디오 재생 중 전화나 다른 오디오 앱이 실행될 때 오디오 인터럽션을 감지하기 위해 사용.
NotificationCenter.default.addObserver(self, selector: #selector(handleAudioSessionInterruption), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
앱 extension(widget, 키보드 등)과 같은 경우, 주 앱과 익스텐션간 데이터를 공유할 때 사용.
NotificationCenter.default.addObserver(self, selector: #selector(bluetoothDidConnect), name: .bluetoothDeviceDidConnect, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(bluetoothDidDisconnect), name: .bluetoothDeviceDidDisconnect, object: nil)