How does NotificationCenter deliver a notification, and on which thread?
Predict first
What does this print?
let nc = NotificationCenter()
let name = Notification.Name("x")
let token = nc.addObserver(forName: name, object: nil, queue: nil) { _ in print("received") }
print("before")
nc.post(name: name, object: nil)
print("after")
nc.removeObserver(token)
nc.post(name: name, object: nil)
print("after remove")
- before, after, received, after remove
- before, received, after, after remove
- before, received, after, received, after remove
Mental model. NotificationCenter is a notice board with a loudspeaker. Posting reads the notice aloud to every listener, and you wait until they have all heard it.
You register an observer for a Notification.Name, and anyone can post that name. Delivery is synchronous: post calls every matching observer one after another and returns only when they have all finished. It happens on the posting thread, unless you pass a queue: to the block-based API, which schedules your block on that queue instead.
The order observers run in is not specified. An object argument filters by sender (nil means any). System events, such as keyboard and app lifecycle changes, arrive this way, so the thread you observe on is whatever the framework posted from.
Posting runs the observer inline, so received comes between the two prints. After removeObserver a second post reaches nobody.
Common traps
- “Notifications are asynchronous.” They are not. A slow observer blocks the poster.
- Updating UI from the observer without checking the thread. It runs on the poster’s thread unless you set a queue.
They might follow up with
- How do you make delivery asynchronous? Pass
queue:, or useNotificationQueueto coalesce and defer postings. - Is the observer order guaranteed? No. Never depend on it.
Related questions
- 2.4.2 How do you avoid leaks and crashes with notification observers?
- 2.4.4 NotificationCenter, delegate, closure or KVO: how do you choose?
How do you avoid leaks and crashes with notification observers? →