NotificationCenter — mahiyyəti, iş prinsipi və bildiriş arxitekturası

Müəllif: IT Sectr Dərc olunub: 2026-03-18 Oxuma vaxtı: 10 dəq

NotificationCenter — bu, göndərən və qəbul edən arasında birbaşa əlaqə olmadan tətbiq komponentləri arasında bildirişlərin göndərilməsi və qəbulu üçün iOS sistem mexanizmidir. Observer nümunəsinə əsaslanan NotificationCenter, obyektlərə hadisələrə abunə olmağa və onlara asinxron reaksiya verməyə imkan verir. Apple Documentation (2025)-ə görə, NSNotificationCenter həm post(name:object:) vasitəsilə sinxron bildiriş göndərməni, həm də NotificationQueue vasitəsilə təxirə salınmış bildirişləri dəstəkləyir. Bildiriş mərkəzi bir proses çərçivəsində işləyir və tətbiq sərhədlərini keçmir.

Əsas məqamlar

  • NotificationCenter — iOS komponentləri arasında hadisə mübadiləsi üçün Observer nümunəsinin tətbiqi.
  • addObserver obyekti müəyyən bir ad və göndərən obyekt ilə bildirişlərə abunə edir.
  • post(name:object:) bütün abunə olunmuş müşahidəçilərə sinxron olaraq bildiriş göndərir.
  • removeObserver deinit-də çağırılması məcburidir, əks halda bildiriş göndərilərkən crash baş verir.
  • NotificationQueue asinxron çatdırılma üçün bildirişləri təxirə salmağa imkan verir.

NotificationCenter nədir?

NotificationCenter (NSNotificationCenter) — bu, obyektlər arasında zəif bağlı kommunikasiyanı həyata keçirmək üçün iOS-un daxili mexanizmidir. Observer nümunəsi bir obyektə (göndərən) birbaşa istinad olmadan bir çox digər obyektləri (müşahidəçiləri) hadisənin baş verməsi barədə xəbərdar etməyə imkan verir. NotificationCenter üç varlıqla işləyir: Notification.Name (bildiriş identifikatoru), Notification (məlumat konteyneri) və NotificationCenter (dispetçer). Hər bir tətbiqin ümumi default center-i var.

NSNotification və Notification.Name

Notification.Name — bildiriş növünü identifikasiya edən strukturdur. extension Name: Notification.Name("MyNotification") vasitəsilə yaradılır. Notification — name, object (göndərən) və userInfo (məlumat lüğəti) olan obyektdir. Sistem bildirişləri sabitlər kimi elan edilir: UIApplication.didBecomeActiveNotification, UIResponder.keyboardWillShowNotification. Xüsusi bildirişlər ad toqquşmalarının qarşısını almaq üçün extension vasitəsilə qruplaşdırılmalıdır. Adlar tərs-domen olmalıdır.

swift
// Xüsusi bildirişlərin təyin edilməsi
extension Notification.Name {
    static let dataDidUpdate =
        Notification.Name("com.app.dataDidUpdate")
    static let userLoggedOut =
        Notification.Name("com.app.userLoggedOut")
}

// Məlumatlarla bildiriş göndərilməsi
let userInfo: [String: Any] = [
    "userId": 123,
    "timestamp": Date()
]
NotificationCenter.default.post(
    name: .dataDidUpdate,
    object: nil,
    userInfo: userInfo
)

Müşahidəçinin əlavə edilməsi (addObserver)

Müşahidəçi addObserver(_:selector:name:object:) metodu ilə bildirişə abunə olur. Selektor — bildiriş alındıqda çağırılacaq metoddur. object parametri müəyyən bir göndərəndən bildirişləri süzməyə imkan verir. object nil olarsa, müşahidəçi göstərilən adla bütün bildirişləri istənilən göndərəndən alır. iOS 9-dan etibarən, block-based API üçün addObserver əl ilə silmə tələb etmir, lakin selector-based hələ də removeObserver tələb edir.

swift
// Bildirişə abunə (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)
}

// Bildirişə abunə (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 necə işləyir?

NotificationCenter xəritələmə cədvəlini saxlayır (name → müşahidəçilər dəsti). Göndərən post(name:object:) çağırdıqda, bildiriş mərkəzi bu ada abunə olan bütün müşahidəçiləri sinxron olaraq gəzir və onların selektorlarını və ya bloklarını çağırır. Əsas xüsusiyyət: post bütün handler-lər tamamlanana qədər cari iplik bloklayır. Handler-lər ağır əməliyyatlar yerinə yetirirsə, bu göndərəni ləngidir. NotificationQueue bildirişlərin çatdırılmasını təxirə salmaqla bu problemi həll edir.

Sinxron göndərmə (post)

post(name:object:userInfo:) metodu bildirişi dərhal bütün müşahidəçilərə göndərir. Çağırış sinxrondur — post-dan sonrakı kod yalnız bütün handler-lər tamamlandıqdan sonra icra olunur. Müşahidəçilərin çağırış sırası təminat verilmir və işə salmalar arasında dəyişə bilər. Ardıcıl emal üçün coalescing ilə NotificationQueue istifadə edin. Eyni bildirişin handler-i içərisində post çağırmayın — bu sonsuz rekursiyaya səbəb olur.

Təxirə salınmış göndərmə (NotificationQueue)

NotificationQueue asinxron çatdırılma üçün bildirişləri növbəyə əlavə edir. Coalescing (eyni bildirişlərin birləşdirilməsi) və çatdırılma növbəsi seçimini (asap, idle, modal) dəstəkləyir. Coalescing tez-tez baş verən hadisələr (yüklənmə vəziyyəti) üçün faydalıdır, yalnız son dəyərlə xəbərdar etmək lazım olduqda. NotificationQueue işə düşmək üçün run loop-dan istifadə edir, buna görə də yalnız aktiv run loop olan ipliklərdə işləyir.

swift
// NotificationQueue vasitəsilə təxirə salınmış göndərmə
let notification = Notification(
    name: .dataDidUpdate,
    object: self,
    userInfo: ["progress": 0.5]
)

// Coalescing: bir neçə bildiriş birinə birləşdirilir
NotificationQueue.default.enqueue(
    notification,
    postingStyle: .whenIdle,
    coalesceMask: .onName,
    forModes: [.common]
)

// DispatchQueue vasitəsilə asinxron göndərmə
DispatchQueue.main.async {
    NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
}

Notification vs Delegate vs KVO

iOS obyektlər arasında ünsiyyət üçün üç əsas mexanizm təqdim edir: NotificationCenter, DelegateKVO (Key-Value Observing). Hər biri bildiriş problemini həll edir, lakin bağlılıq, performans və tip təhlükəsizliyi baxımından fərqli kompromislərlə. Mexanizmin seçimi «bir-birə» və ya «birdən-çoxa» münasibətindən və məlumat ötürmə ehtiyacından asılıdır.

XüsusiyyətNotificationCenterDelegateKVO
BağlılıqZəif (bildiriş adı)Güclü (protokol)Orta (açar)
MünasibətBirdən-çoxaBir-birəBirdən-çoxa
Tip təhlükəsizliyiAşağı (userInfo Dictionary kimi)Yüksək (protokol metodları)Orta (Any?)
PerformansOrta (cədvəl gəzintisi)Yüksək (birbaşa çağırış)Aşağı (NSObject)
AsinxronluqSinxron (post bloklayır)Göndərənin ipliyində sinxronDəyişiklik zamanı sinxron

NotificationCenter nə vaxt seçilməlidir

NotificationCenter bir neçə müstəqil komponentin reaksiya verməli olduğu hadisələr üçün idealdır. Nümunələr: tətbiq parametrlərinin dəyişməsi, istifadəçinin hesabdan çıxması, fonda push bildirişinin alınması. NotificationCenter həmçinin zəif bağlı modullar üçün uyğundur (xüsusiyyət A xüsusiyyət B haqqında bilməməlidir). Çatışmazlıq — tip təhlükəsizliyinin olmaması: userInfo açarları sətirlərdir, enum deyil.

Delegate və ya KVO nə vaxt seçilməlidir

Delegate aydın kontrakt ilə bir-birə münasibət üçün seçin (tableView.delegate). Delegate daha sürətli və tip baxımından daha təhlükəsizdir. KVO modelin konkret xassəsindəki dəyişikliyi müşahidə etmək üçün seçin (isLoading, progress). KVO NSObject-dən miras tələb edir və debug zamanı çətinliklər yarada bilər (sehrli açar sətirləri). Müasir Swift-də Combine və async sequences hər üç yanaşmanı əvəz edir.

AddObserver: sinxron və asinxron bildirişlər

addObserver metodu iki abunə variantını dəstəkləyir: selector-based (ənənəvi) və block-based (closure ilə). Selector-based @objc uyğunluğu və müşahidəçinin əl ilə silinməsini tələb edir. Block-based (iOS 9+) capture list istifadə etməyə imkan verir və güclü istinadlar olmadan bloklardan istifadə edərkən OS tərəfindən avtomatik idarə olunur. Block-based həmçinin queue-ni dəstəkləyir — müşahidəçi bildirişi göstərilən növbədə alır.

Selector-based addObserver

Selektor vasitəsilə ənənəvi abunə üsulu. Handler metodu @objc ilə işarələnməli və optional Notification qəbul etməlidir. Üstünlük: legacy Objective-C də daxil olmaqla istənilən sinif tərəfindən istifadə imkanı. Çatışmazlıqlar: selektorun tip təhlükəsizliyinin olmaması, selektor adında səhv yazma riski, deinit-də məcburi removeObserver. Müşahidəçi obyektdən əvvəl silinərsə, handler çağırılmayacaq.

Block-based addObserver

Block-based API bildiriş alındıqda icra olunan closure qəbul edir. queue parametri blokun hansı növbədə icra olunacağını müəyyən edir — UI yeniləmələri üçün main queue və ya məlumat emalı üçün background queue. Qaytarılan NSObjectProtocol dəyəri müşahidəçinin silinməsi üçün istifadə olunur: NotificationCenter.default.removeObserver(observer). Block-based müasir Swift-də üstünlük verilir.

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

// Avtomatik silinmə ilə istifadə
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() }
    }
}

Yaddaşın idarə edilməsi və müşahidəçilərin silinməsi

Yaddaş sızmaları — NotificationCenter ilə işləyərkən əsas problemlərdən biri. Əgər müşahidəçi dealokasiyadan əvvəl silinməzsə, bildiriş göndərilərkən mərkəz artıq azad edilmiş obyektin metodunu çağırmağa çalışacaq, bu da EXC_BAD_ACCESS-a səbəb olacaq. iOS 9-dan etibarən, block-based addObserver zəif istinadlardan istifadə edir, lakin selector-based hələ də əl ilə removeObserver tələb edir. Best practice: müşahidəçini deinit-də silmək.

removeObserver nə vaxt çağırılmalıdır

Selector-based: deinit-də mütləq NotificationCenter.default.removeObserver(self) çağırın. Əgər müşahidəçi bir neçə bildirişə abunədirsə, hamısını birdən (parametrsiz) və ya konkret adla silmək olar. Block-based: addObserver-dan alınan token ilə removeObserver vasitəsilə silin. iOS 9+ üçün block-based-də sızma baş vermir, lakin silinmə yenə də performans üçün tövsiyə olunur: azad edilmiş müşahidəçilər post zamanı gəzilməyəcək.

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

Token nümunəsi ilə zəif istinadlar

Token nümunəsi müşahidəçilərin idarə edilməsini avtomatlaşdırır. Abunə zamanı token-obyekt (NSObjectProtocol) qaytarılır, o da dealokasiya zamanı avtomatik olaraq müşahidəçini silir. NotificationTokenWrapper NotificationCenter-ə və müşahidəçi tokeninə zəif istinad saxlayır, deinit-də removeObserver çağırır. Bu, NotificationCenter-i Combine yanaşmasına yaxınlaşdırır, burada AnyCancellable abunəliyin həyat dövrünü idarə edir.

Çoxiplikli mühitdə NotificationCenter

Thread safety NotificationCenter zəmanət verir ki, post istənilən iplikdən çağırıla bilər və bütün müşahidəçilər bildirişi post-un çağırıldığı eyni iplikdə alacaqlar. Bu, çoxiplikli tətbiqlər üçün kritik əhəmiyyət daşıyır: əgər bildiriş fon ipliyindən göndərilibsə, handler-lər də fon ipliyində icra olunacaq. UI yeniləməsi üçün DispatchQueue.main.async vasitəsilə emalı main queue-ya göndərmək lazımdır.

post və addObserver-ın iplik təhlükəsizliyi

NotificationCenter müxtəlif ipliklərdən post və addObserver çağırışları üçün iplik təhlükəsizdir. Daxili sinxronizasiya blokirovkadan istifadə edir, buna görə də bir neçə iplikdən tez-tez post çağırışları contention yarada bilər. Yüksək yüklü ssenarilər üçün (1000 faylın yüklənmə vəziyyəti) ayrıca bildiriş növbəsi və ya Combine publisher istifadə edin. postingStyle .now ilə NotificationQueue birbaşa post-a ekvivalentdir.

Combine vasitəsilə asinxron çatdırılma

NotificationCenter Combine publisher-i NotificationCenter.default.publisher(for:object:) vasitəsilə dəstəkləyir. Publisher hər bir bildirişi Combine hadisəsinə çevirir, onu map, filter, debounce və throttle vasitəsilə transformasiya etmək olar. Bu, sinxron çatdırılma problemini həll edir: Combine bildirişləri göstərilən Scheduler-də asinxron emal edir. NotificationCenter.publisher — legacy mexanizm ilə müasir reaktiv proqramlaşdırma arasında körpüdür.

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

Tez-tez verilən suallar

NotificationCenter iplik təhlükəsizdirmi?

Bəli, NotificationCenter istənilən iplikdən post və addObserver çağırışları üçün iplik təhlükəsizdir. Lakin handler-lər post-un çağırıldığı eyni iplikdə icra olunur. UI yeniləməsi üçün block-based addObserver-da queue: .main və ya handler daxilində DispatchQueue.main.async istifadə edin. Combine publisher receive(on:) ilə də iplik problemini həll edir.

Müşahidəçi silinməzsə nə baş verir?

Selector-based: müşahidəçinin dealokasiyasından sonra bildiriş göndərilərkən EXC_BAD_ACCESS crash-i. Block-based (iOS 9+): zəif istinad sayəsində sızma yoxdur, lakin bildiriş mərkəzi aşkar removeObserver-a qədər bloku yaddaşda saxlamağa davam edir. Həmişə müşahidəçini deinit-də silmək və ya avtomatik idarə üçün Token nümunəsindən istifadə etmək tövsiyə olunur.

NotificationCenter və KVO arasında nə fərq var?

NotificationCenter — əlaqəsiz komponentlər arasında ixtiyari hadisələrin yayımı. KVO — konkret obyektin konkret xassəsindəki dəyişikliyin müşahidəsi. KVO NSObject-dən miras tələb edir və setter vasitəsilə xassə dəyişdikdə avtomatik xəbərdar edir. NotificationCenter yalnız aşkar post çağırışı zamanı xəbərdar edir. Modelin müşahidəsi üçün KVO və ya Combine üstünlük təşkil edir.

Tətbiqdə neçə NotificationCenter var?

Tətbiq prosesi üçün bir default center. Əlavə mərkəzlər NotificationCenter() vasitəsilə yaradıla bilər, lakin praktikada ümumi default istifadə olunur. Hər bir mərkəz müstəqil işləyir — birində post digərinin müşahidəçilərinə çatdırılmır. Modulların izolyasiyası üçün bildiriş adlarının tərs-domen adları ilə ayrıca Name fəzalarından istifadə edin.

Combine NotificationCenter-i əvəz edirmi?

Qismən. Combine NotificationCenter.Publisher təqdim edir, o da NotificationCenter-i reaktiv axına bükür. Combine sinxronluq problemini həll edir (receive(on:) vasitəsilə), transformasiya operatorları və avtomatik abunə idarəetməsi (AnyCancellable) əlavə edir. Lakin NotificationCenter sistem iOS bildirişləri (UIApplication, UIKeyboard) və legacy kod üçün qalır. Combine əlavədir, əvəz deyil.

Nəticə

  • NotificationCenter — iOS-da «birdən-çoxa» zəif bağlı kommunikasiya üçün Observer nümunəsinin tətbiqi.
  • post bildirişi cari iplikdə bütün müşahidəçilərə sinxron göndərir, göndərəni bloklayır.
  • addObserver selector-based (@objc ilə) və block-based (capture list və queue ilə) abunəni dəstəkləyir.
  • removeObserver selector-based abunələr üçün deinit-də məcburidir, əks halda crash.
  • NotificationQueue tez-tez baş verən hadisələr üçün coalescing ilə təxirə salınmış çatdırılma təmin edir.
  • Thread safety istənilən iplikdən işləməyə zəmanət verir, lakin handler-lər göndərənin ipliyində icra olunur.
  • Təhlükəsiz və müasir abunə idarəetməsi üçün Token nümunəsi və ya Combine publisher istifadə edin.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun