NotificationCenter — bu jo'natuvchi va qabul qiluvchi o'rtasida to'g'ridan-to'g'ri bog'liqliksiz ilova komponentlari o'rtasida bildirishnomalarni yuborish va qabul qilish uchun iOS tizim mexanizmidir. Observer namunasiga asoslangan NotificationCenter ob'ektlarga hodisalarga obuna bo'lish va ularga asinxron javob berish imkonini beradi. Apple Documentation (2025) ma'lumotlariga ko'ra, NSNotificationCenter post(name:object:) orqali sinxron bildirishnoma yuborishni hamda NotificationQueue orqali kechiktirilgan yuborishni qo'llab-quvvatlaydi. Bildirishnoma markazi bitta jarayon doirasida ishlaydi va ilovalar chegarasidan o'tmaydi.
Asosiy ma'lumotlar
NotificationCenter (NSNotificationCenter) — bu ob'ektlar o'rtasida zaif bog'langan aloqani amalga oshirish uchun iOS-ning o'rnatilgan mexanizmi. Observer namunasi bitta ob'ektga (jo'natuvchi) to'g'ridan-to'g'ri havolasiz ko'plab boshqa ob'ektlarni (kuzatuvchilarni) hodisa yuz bergani haqida xabardor qilish imkonini beradi. NotificationCenter uchta mavjudot bilan ishlaydi: Notification.Name (bildirishnoma identifikatori), Notification (ma'lumot konteyneri) va NotificationCenter (dispetcher). Har bir ilova umumiy default center ga ega.
Notification.Name — bildirishnoma turini identifikatsiya qiluvchi struktura. extension Name: Notification.Name("MyNotification") orqali yaratiladi. Notification — name, object (jo'natuvchi) va userInfo (ma'lumotlar lug'ati) ni o'z ichiga olgan ob'ekt. Tizim bildirishnomalari konstantalar sifatida e'lon qilingan: UIApplication.didBecomeActiveNotification, UIResponder.keyboardWillShowNotification. Maxsus bildirishnomalar nom to'qnashuvlarini oldini olish uchun extension orqali guruhlanishi kerak. Nomlar teskari-domen bo'lishi kerak.
// Maxsus bildirishnomalarni aniqlash
extension Notification.Name {
static let dataDidUpdate =
Notification.Name("com.app.dataDidUpdate")
static let userLoggedOut =
Notification.Name("com.app.userLoggedOut")
}
// Ma'lumotlar bilan bildirishnoma yuborish
let userInfo: [String: Any] = [
"userId": 123,
"timestamp": Date()
]
NotificationCenter.default.post(
name: .dataDidUpdate,
object: nil,
userInfo: userInfo
)
Kuzatuvchi addObserver(_:selector:name:object:) metodi orqali bildirishnomaga obuna bo'ladi. Selektor — bildirishnoma olinganda chaqiriladigan metod. object parametri ma'lum bir jo'natuvchidan bildirishnomalarni filtrlash imkonini beradi. Agar object nil bo'lsa, kuzatuvchi ko'rsatilgan nom bilan barcha bildirishnomalarni har qanday jo'natuvchidan oladi. iOS 9 dan boshlab, addObserver block-based API uchun qo'lda o'chirishni talab qilmaydi, lekin selector-based hali ham removeObserver ni talab qiladi.
// Bildirishnomaga obuna (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)
}
// Bildirishnomaga obuna (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)
}
NotificationCenter xaritalash jadvalini saqlaydi (name → kuzatuvchilar to'plami). Jo'natuvchi post(name:object:) ni chaqirganda, bildirishnoma markazi sinxron ravishda ushbu nomga obuna bo'lgan barcha kuzatuvchilarni aylanib chiqadi va ularning selektorlari yoki bloklarini chaqiradi. Asosiy xususiyat: post barcha handler lar tugaguniga qadar joriy ipni bloklaydi. Agar handler lar og'ir operatsiyalarni bajarayotgan bo'lsa, bu jo'natuvchini kechiktiradi. NotificationQueue bildirishnomalarni yetkazishni kechiktirish orqali bu muammoni hal qiladi.
post(name:object:userInfo:) metodi bildirishnomani darhol barcha kuzatuvchilarga yuboradi. Chaqiruv sinxron — post dan keyingi kod faqat barcha handler lar tugaganidan so'ng bajariladi. Kuzatuvchilarning chaqiruv tartibi kafolatlanmaydi va ishga tushirishlar o'rtasida o'zgarishi mumkin. Ketma-ket ishlov berish uchun coalescing bilan NotificationQueue dan foydalaning. Xuddi shu bildirishnomaning handler i ichida post ni chaqirmang — bu cheksiz rekursiyaga olib keladi.
NotificationQueue asinxron yetkazish uchun bildirishnomalarni navbatga qo'shadi. Coalescing (bir xil bildirishnomalarni birlashtirish) va yetkazish navbatini tanlashni (asap, idle, modal) qo'llab-quvvatlaydi. Coalescing tez-tez sodir bo'ladigan hodisalar (yuklash holati) uchun foydali, faqat oxirgi qiymat bilan xabardor qilish kerak bo'lganda. NotificationQueue ishga tushish uchun run loop dan foydalanadi, shuning uchun faqat faol run loop ga ega iplarda ishlaydi.
// NotificationQueue orqali kechiktirilgan yuborish
let notification = Notification(
name: .dataDidUpdate,
object: self,
userInfo: ["progress": 0.5]
)
// Coalescing: bir nechta bildirishnoma bittaga birlashtiriladi
NotificationQueue.default.enqueue(
notification,
postingStyle: .whenIdle,
coalesceMask: .onName,
forModes: [.common]
)
// DispatchQueue orqali asinxron yuborish
DispatchQueue.main.async {
NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
}
iOS ob'ektlar o'rtasida aloqa uchun uchta asosiy mexanizmni taqdim etadi: NotificationCenter, Delegate va KVO (Key-Value Observing). Har biri bildirish muammosini hal qiladi, lekin bog'liqlik, ishlash va tip xavfsizligi bo'yicha turli kelishuvlar bilan. Mexanizmni tanlash «birga-bir» yoki «birdan-ko'pga» munosabatiga va ma'lumot uzatish zaruratiga bog'liq.
| Xususiyat | NotificationCenter | Delegate | KVO |
|---|---|---|---|
| Bog'liqlik | Zaif (bildirishnoma nomi) | Kuchli (protokol) | O'rta (kalit) |
| Munosabat | Birdan-ko'pga | Birga-bir | Birdan-ko'pga |
| Tip xavfsizligi | Past (userInfo Dictionary sifatida) | Yuqori (protokol metodlari) | O'rta (Any?) |
| Ishlash | O'rta (jadvalni aylanish) | Yuqori (to'g'ridan-to'g'ri chaqiruv) | Past (NSObject) |
| Asinxronlik | Sinxron (post bloklaydi) | Jo'natuvchi ipida sinxron | O'zgarishda sinxron |
NotificationCenter bir nechta mustaqil komponentlar reaksiya ko'rsatishi kerak bo'lgan hodisalar uchun idealdir. Misollar: ilova sozlamalarining o'zgarishi, foydalanuvchining akkauntdan chiqishi, fonda push bildirishnomasini olish. NotificationCenter shuningdek zaif bog'langan modullar uchun ham mos keladi (xususiyat A xususiyat B haqida bilmasligi kerak). Kamchilik — tip xavfsizligining yo'qligi: userInfo kalitlari satrlardir, enum emas.
Delegate aniq kontrakt bilan birga-bir munosabat uchun tanlang (tableView.delegate). Delegate tezroq va tip jihatidan xavfsizroq. KVO modelning aniq xususiyatidagi o'zgarishni kuzatish uchun tanlang (isLoading, progress). KVO NSObject dan meros olishni talab qiladi va disk raskadrovka qilishda qiyinchiliklar tug'dirishi mumkin (sehrli kalit satrlari). Zamonaviy Swift da Combine va async sequences har uch yondashuvni ham almashtiradi.
addObserver metodi ikki xil obuna variantini qo'llab-quvvatlaydi: selector-based (an'anaviy) va block-based (yopilish bilan). Selector-based @objc muvofiqligi va kuzatuvchini qo'lda o'chirishni talab qiladi. Block-based (iOS 9+) capture list dan foydalanish imkonini beradi va kuchli havolalarsiz bloklardan foydalanganda OS tomonidan avtomatik boshqariladi. Block-based shuningdek queue ni qo'llab-quvvatlaydi — kuzatuvchi bildirishnomani ko'rsatilgan navbatda oladi.
Selektor orqali an'anaviy obuna usuli. Handler metodi @objc bilan belgilanishi va ixtiyoriy Notification qabul qilishi kerak. Afzallik: legacy Objective-C hamda istalgan sinf tomonidan foydalanish imkoniyati. Kamchiliklar: selektorning tip xavfsizligining yo'qligi, selektor nomida xato yozish xavfi, deinit da majburiy removeObserver. Kuzatuvchi ob'ektdan oldin o'chirilsa, handler chaqirilmaydi.
Block-based API bildirishnoma olinganda bajariladigan yopilishni qabul qiladi. queue parametri blok qaysi navbatda bajarilishini aniqlaydi — UI yangilanishlari uchun main queue yoki ma'lumotlarni qayta ishlash uchun background queue. Qaytarilgan NSObjectProtocol qiymati kuzatuvchini o'chirish uchun ishlatiladi: NotificationCenter.default.removeObserver(observer). Block-based zamonaviy Swift da afzal ko'riladi.
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)
}
}
// Avtomatik o'chirish bilan foydalanish
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() }
}
}
Xotira sizib chiqishi — NotificationCenter bilan ishlashdagi asosiy muammolardan biri. Agar kuzatuvchi deallokatsiyadan oldin o'chirilmasa, bildirishnoma yuborilganda markaz allaqachon bo'shatilgan ob'ektning metodini chaqirishga harakat qiladi, bu EXC_BAD_ACCESS ga olib keladi. iOS 9 dan boshlab, block-based addObserver zaif havolalardan foydalanadi, lekin selector-based hali ham qo'lda removeObserver ni talab qiladi. Best practice: kuzatuvchini deinit da o'chiring.
Selector-based: deinit da albatta NotificationCenter.default.removeObserver(self) ni chaqiring. Agar kuzatuvchi bir nechta bildirishnomalarga obuna bo'lsa, hammasini birdan (parametrsiz) yoki ma'lum birini nomi bilan o'chirish mumkin. Block-based: addObserver dan olingan token bilan removeObserver orqali o'chiring. iOS 9+ uchun block-based da sizib chiqish sodir bo'lmaydi, lekin o'chirish baribir ishlash uchun tavsiya etiladi: bo'shatilgan kuzatuvchilar post vaqtida aylanib chiqilmaydi.
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() { }
}
Token namunasi kuzatuvchilarni boshqarishni avtomatlashtiradi. Obuna paytida token-ob'ekt (NSObjectProtocol) qaytariladi, u deallokatsiyada avtomatik ravishda kuzatuvchini o'chiradi. NotificationTokenWrapper NotificationCenter ga va kuzatuvchi tokeniga zaif havola saqlaydi, deinit da removeObserver chaqiradi. Bu NotificationCenter ni Combine yondashuviga yaqinlashtiradi, unda AnyCancellable obunaning hayot aylanishini boshqaradi.
Thread safety NotificationCenter post istalgan ipdan chaqirilishi mumkinligini va barcha kuzatuvchilar bildirishnomani post chaqirilgan ipda olishini kafolatlaydi. Bu ko'p iplimli ilovalar uchun juda muhim: agar bildirishnoma fon ipidan yuborilgan bo'lsa, handler lar ham fon ipida bajariladi. UI yangilanishi uchun DispatchQueue.main.async orqali ishlov berishni main queue ga yuborish kerak.
NotificationCenter turli iplardan post va addObserver chaqiruvlari uchun ip xavfsizdir. Ichki sinxronizatsiya blokirovkadan foydalanadi, shuning uchun bir nechta ipdan tez-tez post chaqiruvlari contention yaratishi mumkin. Yuqori yuklamali stsenariylar uchun (1000 ta faylni yuklash holati) alohida bildirishnoma navbatidan yoki Combine publisher dan foydalaning. postingStyle .now bilan NotificationQueue to'g'ridan-to'g'ri post ga teng.
NotificationCenter Combine publisher ni NotificationCenter.default.publisher(for:object:) orqali qo'llab-quvvatlaydi. Publisher har bir bildirishnomani Combine hodisasiga aylantiradi, uni map, filter, debounce va throttle orqali o'zgartirish mumkin. Bu sinxron yetkazish muammosini hal qiladi: Combine bildirishnomalarni ko'rsatilgan Scheduler da asinxron qayta ishlaydi. NotificationCenter.publisher — legacy mexanizm va zamonaviy reaktiv dasturlash o'rtasidagi ko'prikdir.
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)
}
}
Ko'p so'raladigan savollar
Ha, NotificationCenter istalgan ipdan post va addObserver chaqiruvlari uchun ip xavfsizdir. Biroq handler lar post chaqirilgan ipda bajariladi. UI yangilanishi uchun block-based addObserver da queue: .main yoki handler ichida DispatchQueue.main.async dan foydalaning. Combine publisher receive(on:) bilan ham ip muammosini hal qiladi.
Selector-based: kuzatuvchining deallokatsiyasidan keyin bildirishnoma yuborilganda EXC_BAD_ACCESS crash i. Block-based (iOS 9+): zaif havola tufayli sizib chiqish yo'q, lekin bildirishnoma markazi aniq removeObserver gacha blokni xotirada saqlashda davom etadi. Har doim kuzatuvchini deinit da o'chirish yoki avtomatik boshqarish uchun Token namunasidan foydalanish tavsiya etiladi.
NotificationCenter — bog'liq bo'lmagan komponentlar o'rtasida ixtiyoriy hodisalarni tarqatish. KVO — aniq ob'ektning aniq xususiyatidagi o'zgarishni kuzatish. KVO NSObject dan meros olishni talab qiladi va setter orqali xususiyat o'zgarganda avtomatik xabardor qiladi. NotificationCenter faqat aniq post chaqiruvida xabardor qiladi. Modelni kuzatish uchun KVO yoki Combine afzal ko'riladi.
Ilova jarayoni uchun bitta default center. Qo'shimcha markazlar NotificationCenter() orqali yaratilishi mumkin, lekin amalda umumiy default ishlatiladi. Har bir markaz mustaqil ishlaydi — birida post boshqasining kuzatuvchilariga yetkazilmaydi. Modullarni izolyatsiya qilish uchun bildirishnoma nomlarining teskari-domen nomlari bilan alohida Name fazolaridan foydalaning.
Qisman. Combine NotificationCenter.Publisher ni taqdim etadi, u NotificationCenter ni reaktiv oqimga o'rab oladi. Combine sinxronlik muammosini hal qiladi (receive(on:) orqali), transformatsiya operatorlari va avtomatik obuna boshqaruvi (AnyCancellable) qo'shadi. Biroq NotificationCenter tizim iOS bildirishnomalari (UIApplication, UIKeyboard) va legacy kod uchun qoladi. Combine qo'shimcha qatlam, almashtirish emas.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.