NotificationCenter — esensya, prinsipyo ng paggana at arkitektura ng notification

May-akda: IT Sectr Nai-publish: 2026-03-18 Oras ng pagbabasa: 10 min

NotificationCenter — ay isang system mechanism ng iOS para sa pagpapadala at pagtanggap ng mga notification sa pagitan ng mga component ng application nang walang direktang koneksyon sa pagitan ng nagpadala at tumatanggap. Batay sa pattern ng Observer, pinapayagan ng NotificationCenter ang mga object na mag-subscribe sa mga event at tumugon sa mga ito nang asynchronous. Ayon sa Apple Documentation (2025), sinusuportahan ng NSNotificationCenter ang parehong synchronous na pagpapadala ng notification sa pamamagitan ng post(name:object:) at naantalang pagpapadala sa pamamagitan ng NotificationQueue. Ang notification center ay gumagana sa loob ng isang proseso at hindi tumatawid sa mga hangganan ng application.

Mga pangunahing punto

  • NotificationCenter — implementasyon ng Observer pattern para sa pagpapalitan ng event sa pagitan ng mga component ng iOS.
  • addObserver nag-subscribe ng object sa mga notification na may tiyak na pangalan at object ng nagpadala.
  • post(name:object:) nagpapadala ng notification sa lahat ng naka-subscribe na observer nang synchronous.
  • removeObserver ay obligadong tawagin sa deinit, kung hindi ay magkakaroon ng crash kapag nagpapadala ng notification.
  • NotificationQueue ay nagpapahintulot na maantala ang mga notification para sa asynchronous na paghahatid.

Ano ang NotificationCenter?

NotificationCenter (NSNotificationCenter) — ay isang built-in na mekanismo ng iOS para sa pagpapatupad ng maluwag na pagkakaugnay na komunikasyon sa pagitan ng mga object. Ang Observer pattern ay nagpapahintulot sa isang object (nagpadala) na mag-notify ng maraming iba pang object (observer) tungkol sa paglitaw ng isang event nang walang direktang reference sa kanila. Ang NotificationCenter ay nagpapatakbo ng tatlong entity: Notification.Name (identifier ng notification), Notification (container na may data) at NotificationCenter (dispatcher). Bawat application ay may shared default center.

NSNotification at Notification.Name

Notification.Name — ay isang structure na nag-iidentify ng uri ng notification. Ginagawa sa pamamagitan ng extension Name: Notification.Name("MyNotification"). Notification — ay isang object na naglalaman ng name, object (nagpadala) at userInfo (diksyonaryo ng data). Ang mga system notification ay idineklara bilang constants: UIApplication.didBecomeActiveNotification, UIResponder.keyboardWillShowNotification. Ang mga custom na notification ay dapat igrupo sa pamamagitan ng extension upang maiwasan ang banggaan ng pangalan. Ang mga pangalan ay dapat na reverse-domain.

swift
// Pagtukoy ng custom na mga notification
extension Notification.Name {
    static let dataDidUpdate =
        Notification.Name("com.app.dataDidUpdate")
    static let userLoggedOut =
        Notification.Name("com.app.userLoggedOut")
}

// Pagpapadala ng notification na may data
let userInfo: [String: Any] = [
    "userId": 123,
    "timestamp": Date()
]
NotificationCenter.default.post(
    name: .dataDidUpdate,
    object: nil,
    userInfo: userInfo
)

Pagdagdag ng observer (addObserver)

Ang observer ay nag-subscribe sa notification sa pamamagitan ng method na addObserver(_:selector:name:object:). Selector — ang method na tatawagin kapag nakatanggap ng notification. Ang parameter na object ay nagpapahintulot na i-filter ang mga notification mula sa isang tiyak na nagpadala. Kung ang object ay nil, ang observer ay tumatanggap ng lahat ng notification na may tinukoy na pangalan mula sa kahit sinong nagpadala. Simula iOS 9, ang addObserver ay hindi nangangailangan ng manual na pagtanggal para sa block-based API, ngunit ang selector-based ay nangangailangan pa rin ng removeObserver.

swift
// Pag-subscribe sa notification (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)
}

// Pag-subscribe sa notification (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)
}

Paano gumagana ang NotificationCenter?

Ang NotificationCenter ay nag-iimbak ng mapping table (name → set ng mga observer). Kapag ang nagpadala ay tumawag ng post(name:object:), ang notification center ay synchronous na lumilibot sa lahat ng observer na naka-subscribe sa pangalang ito at tumatawag ng kanilang mga selector o block. Pangunahing katangian: ang post ay humaharang sa kasalukuyang thread hanggang sa matapos ang lahat ng handler. Kung ang mga handler ay nagsasagawa ng mabibigat na operasyon, ito ay nagpapaantala sa nagpadala. Niresolba ng NotificationQueue ang problemang ito sa pamamagitan ng pag-antala ng paghahatid ng notification.

Synchronous na pagpapadala (post)

Ang method na post(name:object:userInfo:) ay nagpapadala ng notification kaagad sa lahat ng observer. Ang tawag ay synchronous — ang code pagkatapos ng post ay isinasagawa lamang pagkatapos makumpleto ang lahat ng handler. Ang pagkakasunod-sunod ng tawag ng mga observer ay hindi garantisado at maaaring magbago sa pagitan ng mga pagtakbo. Para sa sequential processing gamitin ang NotificationQueue na may coalescing. Huwag tumawag ng post sa loob ng handler ng parehong notification — ito ay humahantong sa walang hanggang recursion.

Naantalang pagpapadala (NotificationQueue)

NotificationQueue ay nagdadagdag ng mga notification sa queue para sa asynchronous na paghahatid. Sinusuportahan ang coalescing (pagsasama ng magkaparehong notification) at pagpili ng delivery queue (asap, idle, modal). Ang coalescing ay kapaki-pakinabang para sa madalas na mga event (pag-unlad ng pag-load), kung kailan kailangan lamang mag-notify ng huling halaga. Ang NotificationQueue ay gumagamit ng run loop para sa pag-activate, kaya gumagana lamang sa mga thread na may aktibong run loop.

swift
// Naantalang pagpapadala sa pamamagitan ng NotificationQueue
let notification = Notification(
    name: .dataDidUpdate,
    object: self,
    userInfo: ["progress": 0.5]
)

// Coalescing: maraming notification ay pinagsama sa isa
NotificationQueue.default.enqueue(
    notification,
    postingStyle: .whenIdle,
    coalesceMask: .onName,
    forModes: [.common]
)

// Asynchronous na pagpapadala sa pamamagitan ng DispatchQueue
DispatchQueue.main.async {
    NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
}

Notification vs Delegate vs KVO

Ang iOS ay nagbibigay ng tatlong pangunahing mekanismo para sa komunikasyon sa pagitan ng mga object: NotificationCenter, Delegate at KVO (Key-Value Observing). Bawat isa ay lumulutas ng problema ng notification, ngunit may iba't ibang kompromiso sa mga tuntunin ng pagkakaugnay, pagganap at kaligtasan ng uri. Ang pagpili ng mekanismo ay depende sa relasyon na 'isa-sa-isa' o 'isa-sa-marami' at pangangailangan para sa paglipat ng data.

KatangianNotificationCenterDelegateKVO
PagkakaugnayMaluwag (pangalan ng notification)Malakas (protocol)Katamtaman (susi)
RelasyonIsa-sa-maramiIsa-sa-isaIsa-sa-marami
Kaligtasan ng uriMababa (userInfo bilang Dictionary)Mataas (mga method ng protocol)Katamtaman (Any?)
PagganapKatamtaman (paglibot sa table)Mataas (direktang tawag)Mababa (NSObject)
AsynchronySynchronous (post humaharang)Synchronous sa thread ng nagpadalaSynchronous sa pagbabago

Kailan pumili ng NotificationCenter

Ang NotificationCenter ay mainam para sa mga event na dapat tugunan ng maraming independiyenteng component. Halimbawa: pagbabago ng mga setting ng app, pag-logout ng user, pagtanggap ng push notification sa background. Ang NotificationCenter ay angkop din para sa maluwag na pagkakaugnay na mga module (feature A ay hindi kailangang malaman ang tungkol sa feature B). Kakulangan — walang kaligtasan ng uri: ang mga susi ng userInfo ay mga string, hindi enum.

Kailan pumili ng Delegate o KVO

Delegate piliin para sa isa-sa-isang relasyon na may malinaw na kontrata (tableView.delegate). Ang Delegate ay mas mabilis at mas ligtas sa uri. KVO piliin para sa pagmamasid ng pagbabago ng isang tiyak na property ng modelo (isLoading, progress). Ang KVO ay nangangailangan ng pagmamana ng NSObject at maaaring magdulot ng kahirapan sa pag-debug (magical key strings). Sa modernong Swift, ang Combine at async sequences ay pumapalit sa lahat ng tatlong approach.

AddObserver: synchronous at asynchronous na mga notification

Ang method na addObserver ay sumusuporta sa dalawang variant ng subscription: selector-based (tradisyonal) at block-based (na may closure). Selector-based ay nangangailangan ng @objc compatibility at manual na pagtanggal ng observer. Block-based (iOS 9+) ay nagpapahintulot ng paggamit ng capture list at awtomatikong pinamamahalaan ng OS kapag gumagamit ng mga block na walang matibay na reference. Ang block-based ay sumusuporta rin ng queue — ang observer ay tumatanggap ng notification sa tinukoy na queue.

Selector-based addObserver

Tradisyonal na paraan ng subscription sa pamamagitan ng selector. Ang handler method ay dapat mamarkahan ng @objc at tumanggap ng opsyonal na Notification. Bentahe: maaaring gamitin ng kahit anong klase, kabilang ang legacy Objective-C. Disadvantages: walang kaligtasan ng uri ng selector, panganib ng maling type sa pangalan ng selector, obligadong removeObserver sa deinit. Kung ang observer ay tinanggal bago ang object, ang handler ay hindi tatawagin.

Block-based addObserver

Ang block-based API ay tumatanggap ng closure na isinasagawa kapag nakatanggap ng notification. Parameter na queue ay tumutukoy kung saang queue isasagawa ang block — main queue para sa UI updates o background queue para sa pagproseso ng data. Ang ibinalik na NSObjectProtocol na halaga ay ginagamit para sa pagtanggal ng observer: NotificationCenter.default.removeObserver(observer). Ang block-based ay mas gusto sa modernong 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)
    }
}

// Paggamit na may awtomatikong pagtanggal
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() }
    }
}

Pamamahala ng memorya at pagtanggal ng mga observer

Mga tagas ng memorya — isa sa mga pangunahing problema kapag nagtatrabaho sa NotificationCenter. Kung ang observer ay hindi tinanggal bago ang deallocation, kapag nagpapadala ng notification ang center ay susubukan na tawagin ang method ng pinalaya nang object, na hahantong sa EXC_BAD_ACCESS. Simula iOS 9, ang block-based addObserver ay gumagamit ng mahinang reference, ngunit ang selector-based ay nangangailangan pa rin ng manual na removeObserver. Best practice: tanggalin ang observer sa deinit.

Kailan tatawagin ang removeObserver

Selector-based: obligadong tawagin ang NotificationCenter.default.removeObserver(self) sa deinit. Kung ang observer ay naka-subscribe sa maraming notification, maaaring tanggalin lahat nang sabay (walang parameter) o isang tiyak ayon sa pangalan. Block-based: tanggalin sa pamamagitan ng removeObserver na may token na nakuha mula sa addObserver. Para sa block-based sa iOS 9+ walang tagas, ngunit ang pagtanggal ay inirerekomenda pa rin para sa pagganap: ang mga pinalayang observer ay hindi lilibutin sa panahon ng 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() { }
}

Mahinang reference sa pamamagitan ng Token pattern

Ang Token pattern ay nag-automate ng pamamahala ng mga observer. Sa subscription, isang token-object (NSObjectProtocol) ang ibinabalik, na sa deallocation ay awtomatikong nagtatanggal ng observer. NotificationTokenWrapper ay nag-iimbak ng mahinang reference sa NotificationCenter at token ng observer, na tumatawag ng removeObserver sa deinit. Ito ay naglalapit ng NotificationCenter sa Combine approach, kung saan ang AnyCancellable ay namamahala ng lifecycle ng subscription.

NotificationCenter sa multi-thread na kapaligiran

Thread safety ginagarantiya ng NotificationCenter na ang post ay maaaring tawagin mula sa kahit anong thread at lahat ng observer ay makakatanggap ng notification sa parehong thread kung saan tinawag ang post. Ito ay kritikal para sa multi-thread na mga application: kung ang notification ay ipinadala mula sa background thread, ang mga handler ay isasagawa rin sa background thread. Para sa UI update, ang pagproseso ay dapat i-dispatch sa main queue sa pamamagitan ng DispatchQueue.main.async.

Thread safety ng post at addObserver

Ang NotificationCenter ay thread-safe para sa mga tawag ng post at addObserver mula sa iba't ibang thread. Internal na synchronisation ay gumagamit ng locking, kaya ang madalas na post mula sa maraming thread ay maaaring lumikha ng contention. Para sa mga sitwasyong may mataas na karga (pag-unlad ng pag-load ng 1000 file) gumamit ng hiwalay na notification queue o Combine publisher. Ang NotificationQueue na may postingStyle .now ay katumbas ng direktang post.

Asynchronous na paghahatid sa pamamagitan ng Combine

Sinusuportahan ng NotificationCenter ang Combine publisher sa pamamagitan ng NotificationCenter.default.publisher(for:object:). Publisher ay ginagawang Combine event ang bawat notification na maaaring ibahin sa pamamagitan ng map, filter, debounce at throttle. Niresolba nito ang problema ng synchronous na paghahatid: pinoproseso ng Combine ang mga notification nang asynchronous sa tinukoy na Scheduler. Ang NotificationCenter.publisher — ay tulay sa pagitan ng legacy mechanism at modern reactive programming.

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)
    }
}

Mga madalas itanong

Ang NotificationCenter ba ay thread-safe?

Oo, ang NotificationCenter ay thread-safe para sa mga tawag ng post at addObserver mula sa kahit anong thread. Gayunpaman, ang mga handler ay isinasagawa sa parehong thread kung saan tinawag ang post. Para sa UI update gamitin ang queue: .main sa block-based addObserver o DispatchQueue.main.async sa loob ng handler. Ang Combine publisher na may receive(on:) ay lumulutas din ng thread problem.

Ano ang mangyayari kung hindi tinanggal ang observer?

Selector-based: crash EXC_BAD_ACCESS kapag nagpapadala ng notification pagkatapos ng deallocation ng observer. Block-based (iOS 9+): walang tagas dahil sa mahinang reference, ngunit ang notification center ay patuloy na nag-iimbak ng block sa memorya hanggang sa malinaw na removeObserver. Inirerekomenda na palaging tanggalin ang observer sa deinit o gamitin ang Token pattern para sa awtomatikong pamamahala.

Ano ang pagkakaiba sa pagitan ng NotificationCenter at KVO?

NotificationCenter — pag-broadcast ng mga arbitraryong event sa pagitan ng hindi magkakaugnay na component. KVO — pagmamasid ng pagbabago ng isang tiyak na property ng isang tiyak na object. Ang KVO ay nangangailangan ng pagmamana ng NSObject at awtomatikong nagpapaalam kapag nagbago ang property sa pamamagitan ng setter. Ang NotificationCenter ay nagpapaalam lamang sa malinaw na tawag ng post. Para sa pagmamasid ng modelo, ang KVO o Combine ay mas gusto.

Ilang NotificationCenter ang umiiral sa isang application?

Isang default center bawat proseso ng application. Ang mga karagdagang center ay maaaring gawin sa pamamagitan ng NotificationCenter(), ngunit sa praktika ang shared default ay ginagamit. Bawat center ay gumagana nang independiyente — ang post sa isa ay hindi inihahatid sa mga observer ng isa pa. Para sa paghihiwalay ng module, gumamit ng hiwalay na Name namespace sa pamamagitan ng reverse-domain na mga pangalan ng notification.

Pinapalitan ba ng Combine ang NotificationCenter?

Bahagyang. Ang Combine ay nagbibigay ng NotificationCenter.Publisher na bumabalot ng NotificationCenter sa isang reactive stream. Niresolba ng Combine ang problema ng synchrony (sa pamamagitan ng receive(on:)), nagdagdag ng mga transformation operator at awtomatikong pamamahala ng subscription (AnyCancellable). Gayunpaman, ang NotificationCenter ay nananatili para sa mga system notification ng iOS (UIApplication, UIKeyboard) at legacy code. Ang Combine ay isang karagdagan, hindi kapalit.

Buod

  • NotificationCenter — implementasyon ng Observer pattern para sa maluwag na pagkakaugnay na 'isa-sa-marami' na komunikasyon sa iOS.
  • post nagpapadala ng notification nang synchronous sa lahat ng observer sa kasalukuyang thread, hinaharangan ang nagpadala.
  • addObserver sumusuporta sa selector-based (na may @objc) at block-based (na may capture list at queue) na subscription.
  • removeObserver ay obligado sa deinit para sa selector-based subscription, kung hindi crash.
  • NotificationQueue ay nagbibigay ng naantalang paghahatid na may coalescing para sa madalas na mga event.
  • Thread safety ginagarantiya ang operasyon mula sa kahit anong thread, ngunit ang mga handler ay isinasagawa sa thread ng nagpadala.
  • Gamitin ang Token pattern o Combine publisher para sa ligtas at modernong pamamahala ng subscription.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din