NotificationCenter — essentie, werkingsprincipe en architectuur van meldingen

Auteur: IT Sectr Gepubliceerd: 2026-03-18 Leestijd: 10 min

NotificationCenter — is een systeemmechanisme in iOS voor het verzenden en ontvangen van meldingen tussen applicatiecomponenten zonder directe verbinding tussen verzender en ontvanger. Gebaseerd op het Observer-patroon, stelt NotificationCenter objecten in staat zich te abonneren op gebeurtenissen en er asynchroon op te reageren. Volgens Apple Documentation (2025) ondersteunt NSNotificationCenter zowel synchrone verzending via post(name:object:) als uitgestelde verzending via NotificationQueue. Het meldingscentrum werkt binnen één proces en overschrijdt geen applicatiegrenzen.

Belangrijkste punten

  • NotificationCenter — implementatie van het Observer-patroon voor gebeurtenisuitwisseling tussen iOS-componenten.
  • addObserver abonneert een object op meldingen met een specifieke naam en verzendend object.
  • post(name:object:) verzendt de melding synchroon naar alle geabonneerde waarnemers.
  • removeObserver is verplicht in deinit, anders treedt er een crash op bij het verzenden van de melding.
  • NotificationQueue maakt het mogelijk meldingen uit te stellen voor asynchrone levering.

Wat is NotificationCenter?

NotificationCenter (NSNotificationCenter) — is een ingebouwd iOS-mechanisme voor het implementeren van losjes gekoppelde communicatie tussen objecten. Het Observer-patroon stelt één object (verzender) in staat meerdere andere objecten (waarnemers) op de hoogte te stellen van een gebeurtenis zonder directe verwijzing ernaar. NotificationCenter werkt met drie entiteiten: Notification.Name (meldingsidentificatie), Notification (container met gegevens) en NotificationCenter (dispatcher). Elke applicatie heeft een gedeeld default center.

NSNotification en Notification.Name

Notification.Name — is een structuur die het meldingstype identificeert. Wordt gemaakt via extension Name: Notification.Name("MyNotification"). Notification — is een object dat name, object (verzender) en userInfo (woordenboek met gegevens) bevat. Systeemmeldingen zijn gedeclareerd als constanten: UIApplication.didBecomeActiveNotification, UIResponder.keyboardWillShowNotification. Aangepaste meldingen moeten via extension worden gegroepeerd om naamconflicten te voorkomen. Namen moeten omgekeerd-domein zijn.

swift
// Definiëren van aangepaste meldingen
extension Notification.Name {
    static let dataDidUpdate =
        Notification.Name("com.app.dataDidUpdate")
    static let userLoggedOut =
        Notification.Name("com.app.userLoggedOut")
}

// Melding met gegevens verzenden
let userInfo: [String: Any] = [
    "userId": 123,
    "timestamp": Date()
]
NotificationCenter.default.post(
    name: .dataDidUpdate,
    object: nil,
    userInfo: userInfo
)

Waarnemer toevoegen (addObserver)

De waarnemer abonneert zich op een melding via de methode addObserver(_:selector:name:object:). Selector — de methode die wordt aangeroepen bij ontvangst van de melding. De parameter object maakt het mogelijk meldingen van een specifieke verzender te filteren. Als object nil is, ontvangt de waarnemer alle meldingen met de opgegeven naam van elke verzender. Vanaf iOS 9 vereist addObserver geen handmatige verwijdering voor block-based API, maar selector-based vereist nog steeds removeObserver.

swift
// Abonneren op melding (selector-based)
NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleDataUpdate),
    name: .dataDidUpdate,
    object: nil
)

@objc func handleDataUpdate(_ notification: Notification) {
    guard let userId = notification.userInfo?["userId"] as? Int else { return }
    updateUI(for: userId)
}

// Abonneren op melding (block-based, iOS 9+)
var observer: NSObjectProtocol?
observer = NotificationCenter.default.addObserver(
    forName: .dataDidUpdate,
    object: nil,
    queue: .main
) { [weak self] notification in
    guard let self else { return }
    self.handleNotification(notification)
}

Hoe werkt NotificationCenter?

NotificationCenter slaat een mappingtabel op (name → set waarnemers). Wanneer de verzender post(name:object:) aanroept, doorloopt het meldingscentrum synchroon alle waarnemers die op deze naam zijn geabonneerd en roept hun selectors of blokken aan. Belangrijk kenmerk: post blokkeert de huidige thread totdat alle handlers zijn voltooid. Als handlers zware bewerkingen uitvoeren, vertraagt dit de verzender. NotificationQueue lost dit probleem op door de meldingslevering uit te stellen.

Synchrone verzending (post)

De methode post(name:object:userInfo:) verzendt de melding onmiddellijk naar alle waarnemers. De aanroep is synchroon — code na post wordt pas uitgevoerd nadat alle handlers zijn voltooid. De aanroepvolgorde van waarnemers is niet gegarandeerd en kan variëren tussen uitvoeringen. Gebruik voor sequentiële verwerking NotificationQueue met coalescing. Roep post niet aan binnen een handler van dezelfde melding — dit leidt tot oneindige recursie.

Uitgestelde verzending (NotificationQueue)

NotificationQueue voegt meldingen toe aan een wachtrij voor asynchrone levering. Ondersteunt coalescing (samenvoegen van identieke meldingen) en selectie van de leveringswachtrij (asap, idle, modal). Coalescing is handig voor frequente gebeurtenissen (laadvoortgang), wanneer alleen met de laatste waarde hoeft te worden gemeld. NotificationQueue gebruikt run loop om te activeren, dus werkt alleen in threads met een actieve run loop.

swift
// Uitgestelde verzending via NotificationQueue
let notification = Notification(
    name: .dataDidUpdate,
    object: self,
    userInfo: ["progress": 0.5]
)

// Coalescing: meerdere meldingen worden samengevoegd
NotificationQueue.default.enqueue(
    notification,
    postingStyle: .whenIdle,
    coalesceMask: .onName,
    forModes: [.common]
)

// Asynchrone verzending via DispatchQueue
DispatchQueue.main.async {
    NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
}

Notification vs Delegate vs KVO

iOS biedt drie hoofdmechanismen voor communicatie tussen objecten: NotificationCenter, Delegate en KVO (Key-Value Observing). Elk lost het meldingsprobleem op, maar met verschillende afwegingen op het gebied van koppeling, prestaties en typeveiligheid. De keuze van het mechanisme hangt af van de relatie 'een-op-een' of 'een-op-veel' en de noodzaak om gegevens over te dragen.

KenmerkNotificationCenterDelegateKVO
KoppelingLos (meldingsnaam)Sterk (protocol)Gemiddeld (sleutel)
RelatieEen-op-veelEen-op-eenEen-op-veel
TypeveiligheidLaag (userInfo als Dictionary)Hoog (protocolmethoden)Gemiddeld (Any?)
PrestatiesGemiddeld (tabel doorlopen)Hoog (directe aanroep)Laag (NSObject)
AsynchroniteitSynchroon (post blokkeert)Synchroon in thread verzenderSynchroon bij wijziging

Wanneer NotificationCenter kiezen

NotificationCenter is ideaal voor gebeurtenissen waarop meerdere onafhankelijke componenten moeten reageren. Voorbeelden: wijziging van app-instellingen, uitloggen van gebruiker, ontvangen van een pushmelding op de achtergrond. NotificationCenter is ook geschikt voor losjes gekoppelde modules (functie A hoeft niet van functie B te weten). Nadeel — geen typeveiligheid: userInfo-sleutels zijn strings, geen enum.

Wanneer Delegate of KVO kiezen

Delegate kiest u voor een een-op-een relatie met een duidelijk contract (tableView.delegate). Delegate is sneller en typeveiliger. KVO kiest u voor het observeren van een specifieke eigenschap van een model (isLoading, progress). KVO vereist overerving van NSObject en kan problemen veroorzaken bij het debuggen (magische sleutelstrings). In modern Swift vervangen Combine en async sequences alle drie de benaderingen.

AddObserver: synchrone en asynchrone meldingen

De methode addObserver ondersteunt twee abonnementsvarianten: selector-based (traditioneel) en block-based (met closure). Selector-based vereist @objc-compatibiliteit en handmatige verwijdering van de waarnemer. Block-based (iOS 9+) maakt gebruik van capture list mogelijk en wordt automatisch beheerd door het OS bij gebruik van blokken zonder sterke referenties. Block-based ondersteunt ook queue — de waarnemer ontvangt de melding in de opgegeven wachtrij.

Selector-based addObserver

Traditionele manier van abonneren via selector. De handlermethode moet zijn gemarkeerd met @objc en een optionele Notification accepteren. Voordeel: bruikbaar door elke klasse, inclusief legacy Objective-C. Nadelen: geen typeveiligheid van de selector, risico op typefouten in de selectornaam, verplichte removeObserver in deinit. Als de waarnemer vóór het object wordt verwijderd, wordt de handler niet aangeroepen.

Block-based addObserver

Block-based API accepteert een closure die wordt uitgevoerd bij ontvangst van de melding. Parameter queue bepaalt in welke wachtrij het blok wordt uitgevoerd — main queue voor UI-updates of background queue voor gegevensverwerking. De geretourneerde NSObjectProtocol-waarde wordt gebruikt om de waarnemer te verwijderen: NotificationCenter.default.removeObserver(observer). Block-based heeft de voorkeur in modern Swift.

swift
protocol NotificationToken {
    func dispose()
}

extension NotificationCenter {
    func observe(
        name: NSNotification.Name,
        object: Any? = nil,
        queue: OperationQueue? = .main,
        using block: @escaping (Notification) -> Void
    ) -> NotificationToken {
        let observer = addObserver(forName: name, object: object,
                                   queue: queue, using: block)
        return NotificationTokenWrapper(observer: observer, center: self)
    }
}

// Gebruik met automatische verwijdering
class ViewModel {
    private var tokens: [NotificationToken] = []

    func startObserving() {
        let token = NotificationCenter.default.observe(
            name: .dataDidUpdate,
            queue: .main
        ) { [weak self] notification in
            self?.handleUpdate(notification)
        }
        tokens.append(token)
    }

    deinit {
        tokens.forEach { $0.dispose() }
    }
}

Geheugenbeheer en verwijderen van waarnemers

Geheugenlekken — een van de belangrijkste problemen bij het werken met NotificationCenter. Als de waarnemer niet wordt verwijderd vóór deallocatie, zal het centrum bij het verzenden van de melding proberen de methode van het reeds vrijgegeven object aan te roepen, wat leidt tot EXC_BAD_ACCESS. Vanaf iOS 9 gebruikt block-based addObserver zwakke referenties, maar selector-based vereist nog steeds handmatige removeObserver. Best practice: verwijder de waarnemer in deinit.

Wanneer removeObserver aanroepen

Selector-based: roep verplicht NotificationCenter.default.removeObserver(self) aan in deinit. Als de waarnemer op meerdere meldingen is geabonneerd, kunnen ze allemaal tegelijk (zonder parameters) of een specifieke op naam worden verwijderd. Block-based: verwijder via removeObserver met de token verkregen van addObserver. Voor block-based op iOS 9+ treedt geen lek op, maar verwijdering wordt nog steeds aanbevolen voor prestaties: vrijgegeven waarnemers worden niet doorlopen bij post.

swift
class SafeObserver {
    private var observers: [NSObjectProtocol] = []

    func addSubscriptions() {
        let token1 = NotificationCenter.default.addObserver(
            forName: .dataDidUpdate, object: nil,
            queue: .main) { [weak self] _ in
            self?.refreshData()
        }
        let token2 = NotificationCenter.default.addObserver(
            forName: .userLoggedOut, object: nil,
            queue: .main) { [weak self] _ in
            self?.logout()
        }
        observers.append(contentsOf: [token1, token2])
    }

    deinit {
        observers.forEach { NotificationCenter.default.removeObserver($0) }
    }

    private func refreshData() { }
    private func logout() { }
}

Zwakke referenties via Token-patroon

Het Token-patroon automatiseert het beheer van waarnemers. Bij abonnering wordt een token-object (NSObjectProtocol) geretourneerd, dat bij deallocatie automatisch de waarnemer verwijdert. NotificationTokenWrapper slaat een zwakke referentie naar NotificationCenter en de waarnemer-token op, en roept removeObserver aan in deinit. Dit brengt NotificationCenter dichter bij de Combine-benadering, waar AnyCancellable de levenscyclus van het abonnement beheert.

NotificationCenter in een multi-thread omgeving

Thread safety NotificationCenter garandeert dat post vanuit elke thread kan worden aangeroepen en alle waarnemers de melding ontvangen in dezelfde thread waar post is aangeroepen. Dit is cruciaal voor multi-thread applicaties: als de melding vanuit een achtergrondthread is verzonden, worden handlers ook in de achtergrondthread uitgevoerd. Voor UI-updates moet de verwerking naar de main queue worden gedispatched via DispatchQueue.main.async.

Threadveiligheid van post en addObserver

NotificationCenter is threadveilig voor aanroepen van post en addObserver vanuit verschillende threads. Interne synchronisatie gebruikt een vergrendeling, dus frequente post vanuit meerdere threads kan contention veroorzaken. Gebruik voor scenario's met hoge belasting (laadvoortgang van 1000 bestanden) een aparte meldingswachtrij of Combine publisher. NotificationQueue met postingStyle .now is gelijk aan directe post.

Asynchrone levering via Combine

NotificationCenter ondersteunt Combine publisher via NotificationCenter.default.publisher(for:object:). Publisher verandert elke melding in een Combine-gebeurtenis die kan worden getransformeerd via map, filter, debounce en throttle. Dit lost het probleem van synchrone levering op: Combine verwerkt meldingen asynchroon op een opgegeven Scheduler. NotificationCenter.publisher — is een brug tussen het legacy-mechanisme en modern reactief programmeren.

swift
import Combine

class ReactiveViewModel {
    private var cancellables = Set<AnyCancellable>()

    func setupCombineSubscription() {
        NotificationCenter.default
            .publisher(for: .dataDidUpdate)
            .receive(on: DispatchQueue.main)
            .compactMap { $0.userInfo?["progress"] as? Float }
            .debounce(for: .seconds(0.3), scheduler: RunLoop.main)
            .sink { [weak self] progress in
                self?.progressLabel.text = "\(Int(progress * 100))%"
            }
            .store(in: &cancellables)
    }
}

Veelgestelde vragen

Is NotificationCenter threadveilig?

Ja, NotificationCenter is threadveilig voor aanroepen van post en addObserver vanuit elke thread. Handlers worden echter uitgevoerd in dezelfde thread waar post is aangeroepen. Gebruik voor UI-updates queue: .main in block-based addObserver of DispatchQueue.main.async binnen de handler. Combine publisher met receive(on:) lost ook het threadprobleem op.

Wat gebeurt er als de waarnemer niet wordt verwijderd?

Selector-based: crash EXC_BAD_ACCESS bij het verzenden van de melding na deallocatie van de waarnemer. Block-based (iOS 9+): geen lek dankzij zwakke referentie, maar het meldingscentrum blijft het blok in het geheugen houden tot expliciete removeObserver. Het wordt aanbevolen de waarnemer altijd in deinit te verwijderen of het Token-patroon te gebruiken voor automatisch beheer.

Wat is het verschil tussen NotificationCenter en KVO?

NotificationCenter — uitzending van willekeurige gebeurtenissen tussen niet-gerelateerde componenten. KVO — observatie van een specifieke eigenschap van een specifiek object. KVO vereist overerving van NSObject en meldt automatisch bij wijziging van de eigenschap via setter. NotificationCenter meldt alleen bij expliciete aanroep van post. Voor modelobservatie hebben KVO of Combine de voorkeur.

Hoeveel NotificationCenters bestaan er in een applicatie?

Eén default center per applicatieproces. Extra centra kunnen worden gemaakt via NotificationCenter(), maar in de praktijk wordt de gedeelde default gebruikt. Elk centrum werkt onafhankelijk — post in het ene wordt niet bezorgd aan waarnemers van het andere. Gebruik voor module-isolatie aparte Name-naamruimten via omgekeerd-domein meldingsnamen.

Vervangt Combine NotificationCenter?

Gedeeltelijk. Combine biedt NotificationCenter.Publisher die NotificationCenter in een reactieve stroom verpakt. Combine lost het synchronisatieprobleem op (via receive(on:)), voegt transformatieoperators en automatisch abonnementsbeheer (AnyCancellable) toe. NotificationCenter blijft echter voor systeemmeldingen van iOS (UIApplication, UIKeyboard) en legacy-code. Combine is een toevoeging, geen vervanging.

Samenvatting

  • NotificationCenter — implementatie van het Observer-patroon voor losjes gekoppelde 'een-op-veel' communicatie in iOS.
  • post verzendt de melding synchroon naar alle waarnemers in de huidige thread, waarbij de verzender wordt geblokkeerd.
  • addObserver ondersteunt selector-based (met @objc) en block-based (met capture list en queue) abonnementen.
  • removeObserver is verplicht in deinit voor selector-based abonnementen, anders crash.
  • NotificationQueue biedt uitgestelde levering met coalescing voor frequente gebeurtenissen.
  • Thread safety garandeert werking vanuit elke thread, maar handlers worden uitgevoerd in de thread van de verzender.
  • Gebruik het Token-patroon of Combine publisher voor veilig en modern abonnementsbeheer.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook