NotificationCenter — esensi, prinsip kerja dan arsitektur pemberitahuan

Penulis: IT Sectr Diterbitkan: 2026-03-18 Waktu membaca: 10 mnt

NotificationCenter — adalah mekanisme sistem iOS untuk mengirim dan menerima pemberitahuan antar komponen aplikasi tanpa koneksi langsung antara pengirim dan penerima. Berdasarkan pola Observer, NotificationCenter memungkinkan objek berlangganan peristiwa dan bereaksi secara asinkron. Menurut Apple Documentation (2025), NSNotificationCenter mendukung pengiriman pemberitahuan sinkron melalui post(name:object:) maupun pengiriman tertunda melalui NotificationQueue. Pusat pemberitahuan bekerja dalam satu proses dan tidak melintasi batas aplikasi.

Poin utama

  • NotificationCenter — implementasi pola Observer untuk pertukaran peristiwa antar komponen iOS.
  • addObserver mendaftarkan objek pada pemberitahuan dengan nama tertentu dan objek pengirim.
  • post(name:object:) mengirim pemberitahuan ke semua pengamat yang terdaftar secara sinkron.
  • removeObserver wajib dipanggil di deinit, jika tidak akan terjadi crash saat mengirim pemberitahuan.
  • NotificationQueue memungkinkan menunda pemberitahuan untuk pengiriman asinkron.

Apa itu NotificationCenter?

NotificationCenter (NSNotificationCenter) — adalah mekanisme bawaan iOS untuk mengimplementasikan komunikasi terhubung longgar antar objek. Pola Observer memungkinkan satu objek (pengirim) memberi tahu banyak objek lain (pengamat) tentang terjadinya peristiwa tanpa referensi langsung ke mereka. NotificationCenter beroperasi dengan tiga entitas: Notification.Name (pengidentifikasi pemberitahuan), Notification (wadah data) dan NotificationCenter (dispatcher). Setiap aplikasi memiliki default center bersama.

NSNotification dan Notification.Name

Notification.Name — adalah struktur yang mengidentifikasi jenis pemberitahuan. Dibuat melalui extension Name: Notification.Name("MyNotification"). Notification — adalah objek yang berisi name, object (pengirim) dan userInfo (kamus data). Pemberitahuan sistem dideklarasikan sebagai konstanta: UIApplication.didBecomeActiveNotification, UIResponder.keyboardWillShowNotification. Pemberitahuan kustom harus dikelompokkan melalui extension untuk menghindari benturan nama. Nama harus terbalik-domain.

swift
// Mendefinisikan pemberitahuan kustom
extension Notification.Name {
    static let dataDidUpdate =
        Notification.Name("com.app.dataDidUpdate")
    static let userLoggedOut =
        Notification.Name("com.app.userLoggedOut")
}

// Mengirim pemberitahuan dengan data
let userInfo: [String: Any] = [
    "userId": 123,
    "timestamp": Date()
]
NotificationCenter.default.post(
    name: .dataDidUpdate,
    object: nil,
    userInfo: userInfo
)

Menambahkan pengamat (addObserver)

Pengamat berlangganan pemberitahuan melalui metode addObserver(_:selector:name:object:). Selector — metode yang akan dipanggil saat menerima pemberitahuan. Parameter object memungkinkan menyaring pemberitahuan dari pengirim tertentu. Jika object nil, pengamat menerima semua pemberitahuan dengan nama yang ditentukan dari pengirim mana pun. Mulai iOS 9, addObserver tidak memerlukan penghapusan manual untuk block-based API, tetapi selector-based masih memerlukan removeObserver.

swift
// Berlangganan pemberitahuan (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)
}

// Berlangganan pemberitahuan (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)
}

Bagaimana NotificationCenter bekerja?

NotificationCenter menyimpan tabel pemetaan (name → kumpulan pengamat). Saat pengirim memanggil post(name:object:), pusat pemberitahuan secara sinkron menelusuri semua pengamat yang berlangganan nama ini dan memanggil selector atau blok mereka. Fitur utama: post memblokir thread saat ini hingga semua handler selesai. Jika handler menjalankan operasi berat, ini akan menunda pengirim. NotificationQueue memecahkan masalah ini dengan menunda pengiriman pemberitahuan.

Pengiriman sinkron (post)

Metode post(name:object:userInfo:) mengirim pemberitahuan segera ke semua pengamat. Panggilan bersifat sinkron — kode setelah post hanya dijalankan setelah semua handler selesai. Urutan panggilan pengamat tidak dijamin dan dapat berubah antar eksekusi. Untuk pemrosesan berurutan gunakan NotificationQueue dengan coalescing. Jangan memanggil post di dalam handler pemberitahuan yang sama — ini menyebabkan rekursi tak terbatas.

Pengiriman tertunda (NotificationQueue)

NotificationQueue menambahkan pemberitahuan ke antrian untuk pengiriman asinkron. Mendukung coalescing (penggabungan pemberitahuan identik) dan pemilihan antrian pengiriman (asap, idle, modal). Coalescing berguna untuk peristiwa sering (kemajuan pemuatan), ketika perlu memberi tahu hanya dengan nilai terakhir. NotificationQueue menggunakan run loop untuk aktivasi, sehingga hanya berfungsi di thread dengan run loop aktif.

swift
// Pengiriman tertunda melalui NotificationQueue
let notification = Notification(
    name: .dataDidUpdate,
    object: self,
    userInfo: ["progress": 0.5]
)

// Coalescing: beberapa pemberitahuan digabung menjadi satu
NotificationQueue.default.enqueue(
    notification,
    postingStyle: .whenIdle,
    coalesceMask: .onName,
    forModes: [.common]
)

// Pengiriman asinkron melalui DispatchQueue
DispatchQueue.main.async {
    NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
}

Notification vs Delegate vs KVO

iOS menyediakan tiga mekanisme utama untuk komunikasi antar objek: NotificationCenter, Delegate dan KVO (Key-Value Observing). Masing-masing memecahkan masalah pemberitahuan, tetapi dengan kompromi berbeda dalam hal keterhubungan, kinerja, dan keamanan tipe. Pemilihan mekanisme tergantung pada hubungan satu-ke-satu atau satu-ke-banyak dan kebutuhan transfer data.

KarakteristikNotificationCenterDelegateKVO
KeterhubunganLonggar (nama pemberitahuan)Kuat (protokol)Sedang (kunci)
HubunganSatu-ke-banyakSatu-ke-satuSatu-ke-banyak
Keamanan tipeRendah (userInfo sebagai Dictionary)Tinggi (metode protokol)Sedang (Any?)
KinerjaSedang (penelusuran tabel)Tinggi (panggilan langsung)Rendah (NSObject)
AsinkronitasSinkron (post memblokir)Sinkron di thread pengirimSinkron saat perubahan

Kapan memilih NotificationCenter?

NotificationCenter ideal untuk peristiwa yang harus ditanggapi oleh beberapa komponen independen. Contoh: perubahan pengaturan aplikasi, logout pengguna, menerima pemberitahuan push di latar belakang. NotificationCenter juga cocok untuk modul yang terhubung longgar (fitur A tidak perlu tahu tentang fitur B). Kekurangan — tidak ada keamanan tipe: kunci userInfo adalah string, bukan enum.

Kapan memilih Delegate atau KVO?

Delegate pilih untuk hubungan satu-ke-satu dengan kontrak jelas (tableView.delegate). Delegate lebih cepat dan aman secara tipe. KVO pilih untuk mengamati perubahan properti tertentu model (isLoading, progress). KVO memerlukan pewarisan NSObject dan dapat menyulitkan debugging (string kunci ajaib). Di Swift modern, Combine dan async sequences menggantikan ketiga pendekatan.

AddObserver: pemberitahuan sinkron dan asinkron

Metode addObserver mendukung dua varian langganan: selector-based (tradisional) dan block-based (dengan closure). Selector-based memerlukan kompatibilitas @objc dan penghapusan manual pengamat. Block-based (iOS 9+) memungkinkan penggunaan capture list dan dikelola otomatis oleh OS saat menggunakan blok tanpa referensi kuat. Block-based juga mendukung queue — pengamat menerima pemberitahuan di antrian yang ditentukan.

Selector-based addObserver

Cara tradisional berlangganan melalui selector. Metode handler harus ditandai dengan @objc dan menerima Notification opsional. Kelebihan: dapat digunakan oleh kelas apa pun, termasuk legacy Objective-C. Kekurangan: tidak ada keamanan tipe selector, risiko salah ketik nama selector, removeObserver wajib di deinit. Jika pengamat dihapus sebelum objek, handler tidak akan dipanggil.

Block-based addObserver

Block-based API menerima closure yang dijalankan saat menerima pemberitahuan. Parameter queue menentukan di antrian mana blok dijalankan — main queue untuk pembaruan UI atau background queue untuk pemrosesan data. Nilai kembalian NSObjectProtocol digunakan untuk menghapus pengamat: NotificationCenter.default.removeObserver(observer). Block-based lebih disukai di Swift modern.

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

// Penggunaan dengan penghapusan otomatis
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() }
    }
}

Manajemen memori dan penghapusan pengamat

Kebocoran memori — salah satu masalah utama saat bekerja dengan NotificationCenter. Jika pengamat tidak dihapus sebelum dealokasi, saat mengirim pemberitahuan pusat akan mencoba memanggil metode objek yang sudah dibebaskan, menyebabkan EXC_BAD_ACCESS. Mulai iOS 9, block-based addObserver menggunakan referensi lemah, tetapi selector-based masih memerlukan removeObserver manual. Best practice: hapus pengamat di deinit.

Kapan memanggil removeObserver

Selector-based: wajib memanggil NotificationCenter.default.removeObserver(self) di deinit. Jika pengamat berlangganan beberapa pemberitahuan, dapat dihapus semua sekaligus (tanpa parameter) atau spesifik berdasarkan nama. Block-based: hapus melalui removeObserver dengan token yang diperoleh dari addObserver. Untuk block-based di iOS 9+ tidak terjadi kebocoran, tetapi penghapusan tetap disarankan untuk kinerja: pengamat yang dibebaskan tidak akan dilalui saat 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() { }
}

Referensi lemah melalui pola Token

Pola Token mengotomatiskan manajemen pengamat. Saat berlangganan, objek token (NSObjectProtocol) dikembalikan, yang saat dealokasi secara otomatis menghapus pengamat. NotificationTokenWrapper menyimpan referensi lemah ke NotificationCenter dan token pengamat, memanggil removeObserver di deinit. Ini mendekatkan NotificationCenter ke pendekatan Combine, di mana AnyCancellable mengelola siklus hidup langganan.

NotificationCenter di lingkungan multi-thread

Thread safety NotificationCenter menjamin bahwa post dapat dipanggil dari thread mana pun dan semua pengamat akan menerima pemberitahuan di thread yang sama tempat post dipanggil. Ini penting untuk aplikasi multi-thread: jika pemberitahuan dikirim dari thread latar belakang, handler juga akan dijalankan di thread latar belakang. Untuk pembaruan UI, pemrosesan harus didispatch ke main queue melalui DispatchQueue.main.async.

Keamanan thread post dan addObserver

NotificationCenter aman untuk thread untuk panggilan post dan addObserver dari thread berbeda. Sinkronisasi internal menggunakan penguncian, jadi post sering dari beberapa thread dapat membuat contention. Untuk skenario beban tinggi (kemajuan pemuatan 1000 file) gunakan antrian pemberitahuan terpisah atau Combine publisher. NotificationQueue dengan postingStyle .now setara dengan post langsung.

Pengiriman asinkron melalui Combine

NotificationCenter mendukung Combine publisher melalui NotificationCenter.default.publisher(for:object:). Publisher mengubah setiap pemberitahuan menjadi peristiwa Combine yang dapat ditransformasi melalui map, filter, debounce dan throttle. Ini memecahkan masalah pengiriman sinkron: Combine memproses pemberitahuan secara asinkron pada Scheduler yang ditentukan. NotificationCenter.publisher — jembatan antara mekanisme legacy dan pemrograman reaktif modern.

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

Pertanyaan yang sering diajukan

Apakah NotificationCenter aman untuk thread?

Ya, NotificationCenter aman untuk thread untuk panggilan post dan addObserver dari thread mana pun. Namun handler dijalankan di thread yang sama tempat post dipanggil. Untuk pembaruan UI gunakan queue: .main di block-based addObserver atau DispatchQueue.main.async di dalam handler. Combine publisher dengan receive(on:) juga memecahkan masalah thread.

Apa yang terjadi jika pengamat tidak dihapus?

Selector-based: crash EXC_BAD_ACCESS saat mengirim pemberitahuan setelah dealokasi pengamat. Block-based (iOS 9+): tidak ada kebocoran berkat referensi lemah, tetapi pusat pemberitahuan tetap menyimpan blok di memori sampai removeObserver eksplisit. Disarankan selalu menghapus pengamat di deinit atau menggunakan pola Token untuk manajemen otomatis.

Apa perbedaan antara NotificationCenter dan KVO?

NotificationCenter — penyiaran peristiwa arbitrer antar komponen yang tidak terkait. KVO — pengamatan perubahan properti tertentu dari objek tertentu. KVO memerlukan pewarisan NSObject dan memberi tahu secara otomatis saat properti berubah melalui setter. NotificationCenter memberi tahu hanya saat pemanggilan post eksplisit. Untuk pengamatan model, KVO atau Combine lebih disukai.

Berapa banyak NotificationCenter yang ada dalam aplikasi?

Satu default center per proses aplikasi. Pusat tambahan dapat dibuat melalui NotificationCenter(), tetapi dalam praktiknya default bersama digunakan. Setiap pusat bekerja independen — post di satu pusat tidak dikirim ke pengamat pusat lain. Untuk isolasi modul, gunakan ruang nama Name terpisah melalui nama pemberitahuan terbalik-domain.

Apakah Combine menggantikan NotificationCenter?

Sebagian. Combine menyediakan NotificationCenter.Publisher yang membungkus NotificationCenter dalam aliran reaktif. Combine memecahkan masalah sinkronitas (melalui receive(on:)), menambahkan operator transformasi dan manajemen langganan otomatis (AnyCancellable). Namun NotificationCenter tetap ada untuk pemberitahuan sistem iOS (UIApplication, UIKeyboard) dan kode legacy. Combine adalah lapisan tambahan, bukan pengganti.

Ringkasan

  • NotificationCenter — implementasi pola Observer untuk komunikasi longgar satu-ke-banyak di iOS.
  • post mengirim pemberitahuan secara sinkron ke semua pengamat di thread saat ini, memblokir pengirim.
  • addObserver mendukung langganan selector-based (dengan @objc) dan block-based (dengan capture list dan queue).
  • removeObserver wajib di deinit untuk langganan selector-based, jika tidak crash.
  • NotificationQueue menyediakan pengiriman tertunda dengan coalescing untuk peristiwa sering.
  • Thread safety menjamin operasi dari thread mana pun, tetapi handler dijalankan di thread pengirim.
  • Gunakan pola Token atau Combine publisher untuk manajemen langganan yang aman dan modern.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga