Notification Center๋ ๊ฝค๋ ์ค๋์ ๋ถํฐ iOS์ ์ด๋ฒคํธ ์ ์ก ๋งค์ปค๋์ฆ์ผ๋ก ์๋ฆฌ์ก์๋ค. ์ด๋ค ์์๋ค์ด ์๋์ง ํ์ธํด๋ณด์.
Publisher/Subscriber Pattern
NotificationCenter์ ๋ํด ์์๋ณด๊ธฐ ์ด์ ์, ์ด ๋ ์์ด ์ด๋ ํ ๊ธฐ๋ฐ์ ๊ฐ์ง๊ณ ํ์ด๋ ์์ด์ธ์ง ์์๋ณผ ํ์๊ฐ ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก NotificationCenter๋ Publisher/Subscriber Pattern์ ๋ฐ๋ฅธ๋ค. Publisher/Subscriber Pattern์ ๋น๋๊ธฐ ๋ฉ์์ง ํจ๋ฌ๋ค์์ผ๋ก, ๋ฐ์ ์์ ์์ ์๋ก ๊ตฌ๋ถ๋์ด ์๋ค. ์ด ๋, ๋ฐ์ ์์ ๋ฉ์์ง๋ ํน๋ณํ ์์ ์๊ฐ ์ ํด์ ธ์์ง ์์๋ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์๋ค. ์ฆ, ๋ณด๋ด๋๋ฐ ๋ฐ๋ ๋ ์์ด ์์ด๋ ๋๋ค๋ ๋ง์ด๋ค. ๋์ ์์ ํ๋ ์ชฝ์์ ๋ฑ๋กํ๋ ์์ ์ด ํ์ํ๋ค. ์ด ๋, ์์ ์๋ ์ด๋ค ๋ฐ์ ์๋ก๋ถํฐ ๋ฉ์์ง๊ฐ ์ ๋ฌ๋๋์ง์ ๋ํ ์ ๋ณด๋ฅผ ์ ํ์๊ฐ ์๋ค. ์ฆ, ์์ ์ธก์ ์ ๋ณด๋ฅผ ์ ํ ๋ชฐ๋ผ๋ ๋ฉ์์ง๋ฅผ ๋ฐ์ ์ ์๋ค๋ ๋ง์ด๋ค.
์ฌ์ด ์ดํด๋ฅผ ์ํด, ์ฐ๋ฆฌ๊ฐ ์ฐํธ๋ฌผ์ ๋ฐ๋ ๋์์ ์๊ฐํด๋ณด์. ๋๊ตฐ๊ฐ์์ ํธ์ง๋ฅผ ๋๋๋ ์ํฉ์ด์๋ค๋ฉด, A๋ก๋ถํฐ ์ฐ๋ฝ์ด ์ฌ ๊ฒ์ ๊ธฐ๋ํ๊ฒ ๋์ง๋ง, ๋ง์ฝ ๊ตญ๊ฐ๋ก๋ถํฐ ๋ ์์ค๋ ๋ฉ์ธ ์ฐํธ(์ผ์ผ)์ด๋ผ๋ฉด ์ธ์ ๋๊ตฐ๊ฐ์๊ฒ ์ฌ ์ง ์์ํ์ง ๋ชปํ ์ํฉ์์ ๋ฐ๊ฒ ๋๋ค. ์ฆ, ์์ ์์ ์ ๋ณด๋ฅผ ๊ตณ์ด ๋ชจ๋ฅด๋๋ผ๋ ๋ด ์ฐํธํจ์ ์ฐํธ์ด ๋์ฐฉํด์๋ค. ํ์ง๋ง ์ด๋ฌํ ์ฐํธ์ ๋ฐ๊ธฐ ์ํด์ ๋์ ์ฃผ์๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฑ๋กํ ํ์๋ ์๋ค. ๋ง์ฐฌ๊ฐ์ง์ ์๋ฆฌ๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
Pros
๋์จํ ๊ฒฐํฉ์ ๊ฐ์ง๋ค๋ ๊ฒ์ด ์ฅ์ ์ผ๋ก ์์ฉํ ์ ์๊ฒ ๋ค. ์์์ ๋งํ ๊ฒ ์ฒ๋ผ, ๊ฒฐ๊ตญ ์์ ์์ ์ ์ฅ์์๋ ์ด๋ค ๊ฐ์ฒด๊ฐ ๋์๊ฒ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ์ง์ ๋ํ ์ ๋ณด๋ฅผ ๋ชฐ๋ผ๋ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, ํด๋น ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋๋ฐ ์์ด์ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์ฝ๊ฒ ๋์ฒด๊ฐ ๊ฐ๋ฅํ๋ค. ๊ฐ ๊ฐ์ฒด ํน์ ์๋ฒ (์์ผ๋ก๋ ์ถ์์ ๊ฐ๋ ์ผ๋ก ํ ํด๋ก์ง๋ผ ์นญํ๊ฒ ๋ค)๋ ๋ ๋ฆฝ์ ์ผ๋ก ์กด์ฌํ ์ ์๋ค. ๋ง์ฝ ํด๋ผ์ด์ธํธ-์๋ฒ ํจ๋ฌ๋ค์์ด์๋ค๋ฉด, ์๋ฒ ํ๋ก์ธ์ค๊ฐ ์คํ๋์ง ์๋ ๋์ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์์ผ๋ฉฐ, ํด๋ผ์ด์ธํธ ์ญ์ ์คํ๋์ง ์์ผ๋ฉด ์์ ์ด ๋ถ๊ฐ๋ฅํ๋ค. ์ถ๊ฐ์ ์ผ๋ก ์์คํ ํ์ฅ์ฑ์ ๊ฐ์ง ์ ์๋ค. ์ด ๋ถ๋ถ์ ์ ํํ ์ดํดํ์ง ๋ชปํ์ฌ ์ถ๊ฐ ์ ๋ณด๊ฐ ํ์ํ๋ค.
Cons
ํ์ง๋ง ์ด๋ ๊ฒ ๋์จํ ๊ฒฐํฉ(decoupling)์ ๊ฐ์ง๋ค๋ ๊ฒ์ด ํฐ ๊ฒฐ์ ์ผ๋ก ์์ฉํ ์ ์๋ค. ๋ฉ์์ง ์์ ๊ฐ์ฒด๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ PublisherCenter
๋ ๊ฒฐ๊ตญ ๋ฉ์์ง ์ ๋ฌ์ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ์ ์ ์๋ค. ๋ง์ฝ tightํ coupling์ ์งํฅํ๋ ํจํด์ด์๋ค๋ฉด ์ด๋ฅผ ๋ณด์ฅํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณด๋ค ์์ ์ฑ์๋ ํต์ ์ด ๊ฐ๋ฅํ๋ค. ์ด๋ ์์ ์ ์
์ฅ์์๋ ๋ง์ฐฌ๊ฐ์ง๋ฐ, ๊ฒฐ๊ตญ ๋ฉ์์ง๋ฅผ ๋ณด๋๋์ง ๊ทธ๋ ์ง ์์์ง์ ๋ํ ํ๋จ์ ํ ์ ์๋ค.
๋ํ Subscriber์ Publisher์ ๊ฐ์๊ฐ ๋ง์์ง์ ๋ฐ๋ผ, ๊ตํ๋๋ ๋ฉ์์ง์ ์๊ฐ ์ฆ๊ฐํจ์ ๋ฐ๋ผ ์ํคํ ์ณ๊ฐ ๋ถ์ํด์ง๋ค. ํ๋ฒ์ ์ด๋ฒคํธ ๋ฐ์ก์ ๋ธ๋ ค์๋ handler๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ์, ์์ ์์ ๊ฐ์๊ฐ ๋ง์์ง๋ค๋ฉด, ์ด๋ฅผ ์ฐ์ํ์ฌ ์ฒ๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์๊ฐ์ ์ผ๋ก ์์คํ ๋ถํ๊ฐ ๊ฑธ๋ฆด ์ ์๋ค.
๊ฐ์ธ์ ์ผ๋ก ์ฌ์ฉํด๋ณด์์ ๋ ์ด๋ ค์์, ์ ์ญ์ผ๋ก ๊ด๋ฆฌ๋๋ค๋ ์ ์ด์๋ค. ํด๋น ํจ์์ ํธ์ถ์ด ์ด๋์ธ์ง ํ์ ํ๊ธฐ ์ํด์๋ ์ด๋ฅผ postํ๋ ๊ณณ์ ์ฐพ์์ผ ํ๋๋ฐ, decoupling์ด ์ฌํ๋ค๋ณด๋ ๋๋ฒ๊น , ์ ์ง๋ณด์์ ์์ด ์ข์ง ์๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
์ถ๊ฐ์ ์ธ ์ฅ๋จ์ ์ ํด๋น ํจํด์ ๋ํด ๊น์ด ๊ณต๋ถํ ์ดํ์ ํฌ์คํ ์ผ๋ก ๋ง๋ค์ด๋ณด๋๋ก ํ๊ฒ ๋ค.
Notification Center
๊ฐ๋จํ๊ฒ ๋์์ธ ํจํด์ ๋ํด ์์๋ณด์์ผ๋, ์ค์ iOS์์ ์ฌ์ฉํ๋ ๋ฐฉ์์ ์์๋ณด์.
ํฌ๊ฒ ๋ฌ๋ผ์ง ๊ฒ์ ์๋ค. ๋ค๋ง ์ฉ์ด๋ค์ด ์กฐ๊ธ ๋ฌ๋ผ์ก๋ค. PublisherCenter๋ NotificationCenter๋ก, Object๋ ๊ตฌ์ฒด์ ์ผ๋ก Model, View์์ ๋ณด๋ด๋ ๊ฒ์ผ๋ก, ๊ทธ๋ฆฌ๊ณ Subscriber๋ Observer๋ก ๋ช ์นญ์ด ๋ณ๊ฒฝ๋์๋ค. ๊ธฐ๋ณธ์ ์ธ ์๋ฆฌ๋ ๊ฐ์ผ๋, ์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง์ ๋ํด ์์๋ณด์.
Custom Notification
class ViewController {
// 1. Get NotificationCenter Instance
let notificationCenter = NotificationCenter.default
override func viewDidLoad() {
super.viewDidLoad()
// 2. Custom Notification Name
let notificationName = Notification.Name("NotificationName")
// 3. Add Observer - Register and Observe for changes
notificationCenter.addObserver(self, // 2a. An object to register as an observer.
selector: #selector(myMethod(_:)), // 2b. Method what will be called if Notification triggers
name: notificationName, // 2c. Name of the Notification to know to Identify the message
object: nil)
}
@objc func myMethod(_ notification: NSNotification) {
// 4. The call
// 4a. In case the message is passing some data it is in 'notification.userInfo'
}
}
class Model {
func postNotification() {
let notificationName = Notification.Name("NotificationName")
let message = ["message_key": "message_value"]
Notification.default.post(name: notificationName, object: self, userInfo: message) // ๋ฐ์ ์๋ฅผ ์๋ฆฌ๊ณ ์ถ๋ค๋ฉด object์ ๋ฃ์ด์ฃผ์
}
}
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ์์ ์๊ฐํด๋ณด๋๋ก ํ๊ฒ ๋ค. ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.
- Notification Instance๋ฅผ ๋ง๋ ๋ค.
- NotificationCenter์ ๋ฑ๋กํ NotificationName instance๋ฅผ ๋ง๋ ๋ค.
- Observeํ์ฌ ๋์์ ์คํํ๊ณ ์ถ์ ๊ฐ์ฒด์์ Observer๋ฅผ ์ถ๊ฐํ๋ค.
selector
์ฌ์ฉ: objective-C runtime ์ฌ์ฉ,@objc
ํค์๋ ์๊ตฌ๋จ, ๋๊ธฐ ๋ฐฉ์- handler ์ฌ์ฉ: queue ์ง์ ์ ํตํด ๋น๋๊ธฐ ๋ฐฉ์ ์ ์ฉ ๊ฐ๋ฅ
- ์ํ๋ ํจ์๊ฐ ํธ์ถ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ ์ก๋์ด์ผ ํ๋ ๊ฒฝ์ฐ userInfo๋ก ์ ๋ฌํ๋ค.
- (์ฝ๋์๋ ์์ง๋ง) ์ฑ ํ๊ฒ์ด iOS 9.0, macOS 10.11 ์ด์ ์ด๋ผ๋ฉด ๋ฑ๋กํ observer๋ฅผ ์ ๊ฑฐํด์ฃผ์ด์ผ ํ๋ค. ์ดํ์ ๊ฒฝ์ฐ system์ด ์ ๊ฑฐํด์ค๋ค.
- ์ ๋ณด๋ฅผ ๋ณด๋ด๋ ์ชฝ์์๋ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด
post
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด๋ธ๋ค.
@objc extension NSNotification {
public static let myCustomNotificationName = Notification.Name.myCustomNotificationName
}
extension Notification.Name { }
์ผ๋ก ์ถ๊ฐํ์ฌ ์ฌ์ฉ๋ ๊ฐ๋ฅํ๋ค. ํ์ง๋ง ์ ์ญ ์ค์ฝํ๋ก ๊ด๋ฆฌ๋๋ ๋ถ๋ถ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์ถ๋ค๋ฉด ํด๋น ๋ฐฉ๋ฒ์ ์ข์ง ์์ ์ ์๋ค. ํด๋น Name์ ๊ด๋ฆฌํด์ผ ํ๋ ๊ฐ์ฒด๊ฐ ๋๊ฐ ๋์ด์ผ ํ๋์ง ์๊ฐํ๋ ๊ฒ์ด ์ข๋ค.
NotificationCenter Sync
func addObserver(_ observer: Any,
selector aSelector: Selector,
name aName: NSNotification.Name?,
object anObject: Any?)
์ ๋ฐฉ์์ผ๋ก observer๋ฅผ ๋ฑ๋กํ๋ ๊ฒ์๋ ๋๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค๊ณ ํ๋ค. ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๋ฐฉ์์ ๋๊ธฐ ๋ฐฉ์์ด๋ค. ๊ฐํธํ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
NotificationCenter Async
func addObserver(forName name: NSNotification.Name?,
object obj: Any?,
queue: OperationQueue?,
using block: @escaping (Notification) -> Void) -> NSObjectProtocol
Pub/Sub ํจํด์์ ๋ง์ subscriber๊ฐ ์ฐ๊ฒฐ๋์ด ์์ ์ ๋ถํ๊ฐ ๊ฑธ๋ฆด ์ ์๋ค๋ ๋ฌธ์ ๊ฐ ์์๋ค. ์ด๋ฌํ ์ ์์ ๋น๋๊ธฐ์ ์ธ ํด๊ฒฐ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์๋๋ฐ, ์์ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. queue๊ฐ nil
์ธ ๊ฒฝ์ฐ ๋๊ธฐ์ ์ผ๋ก ์๋๋๋ค. ํด๋น ํจ์๋ selector
๋ฅผ ์ฌ์ฉํ๋ ๋๊ธฐ ๋ฉ์๋์ ๋ค๋ฅด๊ฒ, return value๋ฅผ ๊ฐ์ง๋ค. ๋ง์ฝ ์ค๊ฐ์ observing์ ๊ทธ๋งํ๊ณ ์ถ๋ค๋ฉด, ํด๋น return value๋ฅผ ๋ณ์๋ก ๊ฐ์ง๊ณ ์๋ค๊ฐ, center.removeObserver(self.observer)
์ ๊ฐ์ ํ์์ผ๋ก ์ ๊ฑฐํด์ฃผ์ด์ผ ํ๋ค. ๋ง์ฝ ํ๋ฒ๋ง observingํ๊ณ ๊ทธ๋ง ๋๊ณ ์ถ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ ์ถ์ฒํ๋ค๊ณ ํ๋ค.
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
var token: NSObjectProtocol?
token = center.addObserverForName("OneTimeNotification", object: nil, queue: mainQueue) { (note) in
print("Received the notification!")
center.removeObserver(token!)
}
OS provided Notification
iOS์์๋ ์ด NotificationCenter๋ฅผ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ์ค์ด๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ฒ๋ค์ด ์๋ค. ์ถ๊ฐ์ ์ผ๋ก ๊ถ๊ธํ๋ค๋ฉด NSNotification.Name๋ฅผ ์ฐธ๊ณ ํ์.
static let elementFocusedNotification: NSNotification.Name
static let boldTextStatusDidChangeNotification: NSNotification.Name
class let didBecomeActiveNotification: NSNotification.Name
class let didReceiveMemoryWarningNotification: NSNotification.Name
class let textDidChangeNotification: NSNotification.Name
class let batteryLevelDidChangeNotification: NSNotification.Name
class let keyboardWillShowNotification: NSNotification.Name
์์ ๋ณด์ด๋ didBecomeActiveNotification
์ ๊ฒฝ์ฐ, AppDelegate
์์์ applicationDidBecomeActive(_:)
ํน์ SceneDelegate
์ sceneDidBecomeActive(_:)
์ ๋์ผํ๋ค. ๊ธฐ์กด์๋ ๊ฐ๊ฐ์ ์์ค ํ์ผ ๋ด๋ถ์์ ์ด๋ฅผ ๊ด๋ฆฌํ ์ ๋ฐ์ ์์๋ค๋ฉด, ์ด์ ์ด NotificationName
์ผ๋ก Observingํ๋ค๋ฉด, OS๊ฐ ๊ด๋ฆฌํ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ์์ ์, ๋ด๊ฐ ์ํ๋ ๋์์ ์ํํ๋๋ก ํ ์ ์์ ๊ฒ์ด๋ค.
Sum up
- NotificationCenter๋ Pub/Sub pattern์ ์ฌ์ฉํ ๋ฉ์์ง ์ ์ก ๊ฐ์ฒด์ด๋ค.
- Custom์ผ๋ก ๋ง๋ค์ด์ ์ฌ์ฉํ ์ ์๊ณ , System์์ ์ ๊ณตํ๋ ๋ ์์ ์ฌ์ฉํ ์๋ ์๋ค.
- selector๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ iOS 9.0 ์ด์ ์ด๋ผ๋ฉด observer๋ฅผ ๋ช ์์ ์ผ๋ก ์ง์์ฃผ์ด์ผ ํ๋ค.
- ๋น๋๊ธฐ์ ์ผ๋ก ๋ฉ์์ง๋ฅผ ์์ ํ๋ method๋ ์กด์ฌํ๋ค.
์ค๋์ ๊ฐ๋จํ๊ฒ NotificationCenter์ ๋ํด ์์๋ณด์๋ค. ๋ง์ฝ Combine ํ์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด 03. Notification To Combine์ ์ฝ์ด๋ณด์. ๋!