NotificationCenter iOS में एप्लिकेशन घटकों के बीच प्रेषक और प्राप्तकर्ता के बीच सीधे कनेक्शन के बिना सूचनाएँ भेजने और प्राप्त करने के लिए एक सिस्टम तंत्र है। Observer पैटर्न पर आधारित, NotificationCenter ऑब्जेक्ट्स को ईवेंट्स की सदस्यता लेने और उन पर अतुल्यकालिक रूप से प्रतिक्रिया करने की अनुमति देता है। Apple Documentation (2025) के अनुसार, NSNotificationCenter post(name:object:) के माध्यम से तुल्यकालिक सूचना भेजने और NotificationQueue के माध्यम से विलंबित भेजने दोनों का समर्थन करता है। सूचना केंद्र एक प्रक्रिया के भीतर काम करता है और एप्लिकेशन सीमाओं को पार नहीं करता है।
मुख्य बिंदु
NotificationCenter (NSNotificationCenter) ऑब्जेक्ट्स के बीच शिथिल रूप से युग्मित संचार को लागू करने के लिए एक अंतर्निहित iOS तंत्र है। Observer पैटर्न एक ऑब्जेक्ट (प्रेषक) को उनके सीधे संदर्भ के बिना कई अन्य ऑब्जेक्ट्स (प्रेक्षकों) को किसी ईवेंट के बारे में सूचित करने की अनुमति देता है। NotificationCenter तीन संस्थाओं के साथ संचालित होता है: Notification.Name (सूचना पहचानकर्ता), Notification (डेटा वाला कंटेनर) और NotificationCenter (डिस्पैचर)। प्रत्येक एप्लिकेशन में एक साझा default center होता है।
Notification.Name एक संरचना है जो सूचना प्रकार की पहचान करती है। extension Name: Notification.Name(“MyNotification”) के माध्यम से बनाई जाती है। Notification एक ऑब्जेक्ट है जिसमें name, object (प्रेषक) और userInfo (डेटा वाला शब्दकोश) होता है। सिस्टम सूचनाएँ स्थिरांक के रूप में घोषित की जाती हैं: UIApplication.didBecomeActiveNotification, UIResponder.keyboardWillShowNotification। कस्टम सूचनाओं को नाम टकराव से बचने के लिए extension के माध्यम से समूहित किया जाना चाहिए। नाम रिवर्स-डोमेन होने चाहिए।
// कस्टम सूचनाओं को परिभाषित करना
extension Notification.Name {
static let dataDidUpdate =
Notification.Name("com.app.dataDidUpdate")
static let userLoggedOut =
Notification.Name("com.app.userLoggedOut")
}
// डेटा के साथ सूचना भेजना
let userInfo: [String: Any] = [
"userId": 123,
"timestamp": Date()
]
NotificationCenter.default.post(
name: .dataDidUpdate,
object: nil,
userInfo: userInfo
)
एक प्रेक्षक addObserver(_:selector:name:object:) विधि के माध्यम से सूचना की सदस्यता लेता है। Selector वह विधि है जो सूचना प्राप्त होने पर कॉल की जाएगी। object पैरामीटर किसी विशिष्ट प्रेषक से सूचनाओं को फ़िल्टर करने की अनुमति देता है। यदि object nil है, तो प्रेक्षक किसी भी प्रेषक से निर्दिष्ट नाम वाली सभी सूचनाएँ प्राप्त करता है। iOS 9 से, addObserver को block-based API के लिए मैन्युअल निष्कासन की आवश्यकता नहीं है, लेकिन selector-based को अभी भी removeObserver की आवश्यकता है।
// सूचना की सदस्यता लेना (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)
}
// सूचना की सदस्यता लेना (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 एक मैपिंग तालिका (नाम → प्रेक्षकों का सेट) संग्रहीत करता है। जब प्रेषक post(name:object:) कॉल करता है, तो सूचना केंद्र तुल्यकालिक रूप से उस नाम की सदस्यता वाले सभी प्रेक्षकों को पार करता है और उनके सेलेक्टर या ब्लॉक कॉल करता है। मुख्य विशेषता: post सभी हैंडलर के पूरा होने तक वर्तमान थ्रेड को ब्लॉक करता है। यदि हैंडलर भारी संचालन करते हैं, तो यह प्रेषक में देरी करता है। NotificationQueue सूचना वितरण में देरी करके इस समस्या को हल करता है।
post(name:object:userInfo:) विधि तुरंत सभी प्रेक्षकों को सूचना भेजती है। कॉल तुल्यकालिक है — post के बाद का कोड सभी हैंडलर के पूरा होने के बाद ही निष्पादित होता है। प्रेक्षकों के आह्वान का क्रम गारंटीड नहीं है और लॉन्च के बीच बदल सकता है। अनुक्रमिक प्रसंस्करण के लिए, coalescing के साथ NotificationQueue का उपयोग करें। उसी सूचना के हैंडलर के अंदर post कॉल न करें — इससे अनंत पुनरावृत्ति होती है।
NotificationQueue अतुल्यकालिक वितरण के लिए सूचनाओं को कतार में जोड़ता है। यह coalescing (समान सूचनाओं का विलय) और वितरण कतार चयन (asap, idle, modal) का समर्थन करता है। Coalescing बार-बार होने वाली घटनाओं (डाउनलोड प्रगति) के लिए उपयोगी है जब आपको केवल नवीनतम मान से सूचित करने की आवश्यकता होती है। NotificationQueue सक्रिय होने के लिए रन लूप का उपयोग करता है, इसलिए यह केवल सक्रिय रन लूप वाले थ्रेड में काम करता है।
// NotificationQueue के माध्यम से विलंबित भेजना
let notification = Notification(
name: .dataDidUpdate,
object: self,
userInfo: ["progress": 0.5]
)
// Coalescing: कई सूचनाएँ एक में विलीन हो जाती हैं
NotificationQueue.default.enqueue(
notification,
postingStyle: .whenIdle,
coalesceMask: .onName,
forModes: [.common]
)
// DispatchQueue के माध्यम से अतुल्यकालिक वितरण
DispatchQueue.main.async {
NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
}
iOS ऑब्जेक्ट्स के बीच संचार के लिए तीन मुख्य तंत्र प्रदान करता है: NotificationCenter, Delegate और KVO (Key-Value Observing)। प्रत्येक सूचना की समस्या को हल करता है लेकिन युग्मन, प्रदर्शन और प्रकार सुरक्षा में विभिन्न समझौतों के साथ। तंत्र का चुनाव एक-से-एक या एक-से-अनेक संबंध और डेटा स्थानांतरण की आवश्यकता पर निर्भर करता है।
| विशेषता | NotificationCenter | Delegate | KVO |
|---|---|---|---|
| युग्मन | कमज़ोर (सूचना नाम) | मज़बूत (प्रोटोकॉल) | मध्यम (कुंजी) |
| संबंध | एक-से-अनेक | एक-से-एक | एक-से-अनेक |
| प्रकार सुरक्षा | निम्न (userInfo Dictionary के रूप में) | उच्च (प्रोटोकॉल विधियाँ) | मध्यम (Any?) |
| प्रदर्शन | मध्यम (तालिका पार करना) | उच्च (सीधा कॉल) | निम्न (NSObject) |
| अतुल्यकालिकता | तुल्यकालिक (post ब्लॉक करता है) | प्रेषक के थ्रेड में तुल्यकालिक | परिवर्तन पर तुल्यकालिक |
NotificationCenter उन घटनाओं के लिए आदर्श है जिन पर कई स्वतंत्र घटकों को प्रतिक्रिया देनी चाहिए। उदाहरण: एप्लिकेशन सेटिंग्स में बदलाव, उपयोगकर्ता लॉगआउट, पृष्ठभूमि में पुश सूचना प्राप्त करना। NotificationCenter शिथिल युग्मित मॉड्यूल (फीचर A को फीचर B के बारे में नहीं जानना चाहिए) के लिए भी उपयुक्त है। कमी प्रकार सुरक्षा की कमी है: userInfo कुंजियाँ स्ट्रिंग हैं, एनम नहीं।
Delegate स्पष्ट अनुबंध (tableView.delegate) वाले एक-से-एक संबंधों के लिए विकल्प है। Delegate तेज़ और प्रकारों द्वारा अधिक सुरक्षित है। KVO मॉडल की किसी विशिष्ट संपत्ति (isLoading, progress) में परिवर्तन देखने के लिए विकल्प है। KVO को NSObject से वंशानुक्रम की आवश्यकता होती है और डिबगिंग में कठिनाइयाँ पैदा कर सकता है (जादुई स्ट्रिंग कुंजियाँ)। आधुनिक Swift में, Combine और async sequences तीनों दृष्टिकोणों को बदल देते हैं।
addObserver विधि दो सदस्यता प्रकारों का समर्थन करती है: selector-based (पारंपरिक) और block-based (क्लोज़र के साथ)। Selector-based के लिए @objc संगतता और मैन्युअल प्रेक्षक निष्कासन आवश्यक है। Block-based (iOS 9+) कैप्चर सूची का उपयोग करने की अनुमति देता है और मजबूत संदर्भों के बिना ब्लॉक का उपयोग करते समय OS द्वारा स्वचालित रूप से प्रबंधित किया जाता है। Block-based कतार का भी समर्थन करता है — प्रेक्षक निर्दिष्ट कतार में सूचना प्राप्त करता है।
सेलेक्टर के माध्यम से सदस्यता लेने का पारंपरिक तरीका। हैंडलर विधि को @objc से चिह्नित किया जाना चाहिए और एक वैकल्पिक Notification स्वीकार करना चाहिए। लाभ: किसी भी वर्ग द्वारा उपयोग किया जा सकता है, जिसमें लीगेसी Objective-C शामिल है। नुकसान: सेलेक्टर के लिए प्रकार सुरक्षा की कमी, सेलेक्टर नाम में टाइपो का जोखिम, deinit में अनिवार्य removeObserver। यदि प्रेक्षक को ऑब्जेक्ट से पहले हटा दिया जाता है, तो हैंडलर कॉल नहीं किया जाएगा।
Block-based API एक क्लोज़र स्वीकार करता है जो सूचना प्राप्त होने पर निष्पादित होता है। queue पैरामीटर यह निर्धारित करता है कि ब्लॉक किस कतार में चलता है — UI अपडेट के लिए मुख्य कतार या डेटा प्रसंस्करण के लिए पृष्ठभूमि कतार। रिटर्न वैल्यू NSObjectProtocol का उपयोग प्रेक्षक को हटाने के लिए किया जाता है: NotificationCenter.default.removeObserver(observer)। आधुनिक Swift में Block-based पसंद किया जाता है।
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)
}
}
// स्वचालित निष्कासन के साथ उपयोग
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() }
}
}
मेमोरी लीक NotificationCenter के साथ काम करते समय मुख्य समस्याओं में से एक है। यदि डीलोकेशन से पहले प्रेक्षक को नहीं हटाया जाता है, तो सूचना भेजने पर केंद्र पहले से डीलोकेटेड ऑब्जेक्ट पर एक विधि कॉल करने का प्रयास करेगा, जिसके परिणामस्वरूप EXC_BAD_ACCESS होगा। iOS 9 से, block-based addObserver कमज़ोर संदर्भों का उपयोग करता है, लेकिन selector-based को अभी भी मैन्युअल removeObserver की आवश्यकता है। सर्वोत्तम अभ्यास: deinit में प्रेक्षक को हटाएँ।
Selector-based: हमेशा deinit में NotificationCenter.default.removeObserver(self) कॉल करें। यदि प्रेक्षक कई सूचनाओं की सदस्यता लेता है, तो आप सभी को एक साथ (बिना पैरामीटर के) या नाम से विशिष्ट एक को हटा सकते हैं। Block-based: addObserver से प्राप्त टोकन के साथ removeObserver के माध्यम से हटाएँ। iOS 9+ पर block-based के लिए, लीक नहीं होता है, लेकिन प्रदर्शन के लिए निष्कासन अभी भी अनुशंसित है: डीलोकेटेड प्रेक्षक post के दौरान पार नहीं किए जाएँगे।
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() { }
}
टोकन पैटर्न प्रेक्षक प्रबंधन को स्वचालित करता है। सदस्यता पर, एक टोकन ऑब्जेक्ट (NSObjectProtocol) लौटाया जाता है जो डीलोकेशन पर स्वचालित रूप से प्रेक्षक को हटा देता है। NotificationTokenWrapper NotificationCenter और प्रेक्षक टोकन के लिए एक कमज़ोर संदर्भ संग्रहीत करता है, deinit में removeObserver कॉल करता है। यह NotificationCenter को Combine दृष्टिकोण के करीब लाता है, जहाँ AnyCancellable सदस्यता जीवनचक्र का प्रबंधन करता है।
थ्रेड सुरक्षा: NotificationCenter गारंटी देता है कि post किसी भी थ्रेड से कॉल किया जा सकता है, और सभी प्रेक्षक उसी थ्रेड पर सूचना प्राप्त करेंगे जहाँ post कॉल किया गया था। यह मल्टीथ्रेडेड एप्लिकेशन के लिए महत्वपूर्ण है: यदि पृष्ठभूमि थ्रेड से सूचना भेजी जाती है, तो हैंडलर भी पृष्ठभूमि थ्रेड पर निष्पादित होंगे। UI अपडेट के लिए, DispatchQueue.main.async के माध्यम से हैंडलिंग को मुख्य कतार पर भेजें।
NotificationCenter विभिन्न थ्रेड से post और addObserver कॉल के लिए थ्रेड-सुरक्षित है। आंतरिक सिंक्रनाइज़ेशन लॉकिंग का उपयोग करता है, इसलिए कई थ्रेड से बार-बार post प्रतिस्पर्धा पैदा कर सकते हैं। उच्च-लोड परिदृश्यों (1000 फ़ाइलों की डाउनलोड प्रगति) के लिए, एक अलग सूचना कतार या Combine publisher का उपयोग करें। postingStyle .now के साथ NotificationQueue सीधे post के बराबर है।
NotificationCenter NotificationCenter.default.publisher(for:object:) के माध्यम से Combine publisher का समर्थन करता है। Publisher प्रत्येक सूचना को Combine ईवेंट में बदल देता है जिसे map, filter, debounce और throttle के माध्यम से रूपांतरित किया जा सकता है। यह तुल्यकालिक वितरण समस्या को हल करता है: Combine निर्दिष्ट Scheduler पर सूचनाओं को अतुल्यकालिक रूप से संसाधित करता है। NotificationCenter.publisher विरासत तंत्र और आधुनिक रिएक्टिव प्रोग्रामिंग के बीच एक पुल है।
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)
}
}
अक्सर पूछे जाने वाले प्रश्न
हाँ, NotificationCenter किसी भी थ्रेड से post और addObserver कॉल के लिए थ्रेड-सुरक्षित है। हालाँकि, हैंडलर उसी थ्रेड पर निष्पादित होते हैं जहाँ post कॉल किया गया था। UI अपडेट के लिए, block-based addObserver में queue: .main का उपयोग करें या हैंडलर के अंदर DispatchQueue.main.async का उपयोग करें। receive(on:) के साथ Combine publisher भी थ्रेड समस्या को हल करता है।
Selector-based: प्रेक्षक डीलोकेशन के बाद सूचना भेजने पर क्रैश EXC_BAD_ACCESS। Block-based (iOS 9+): कमज़ोर संदर्भ के कारण कोई लीक नहीं, लेकिन सूचना केंद्र स्पष्ट removeObserver तक ब्लॉक को मेमोरी में रखता है। हमेशा deinit में प्रेक्षक को हटाने या स्वचालित प्रबंधन के लिए टोकन पैटर्न का उपयोग करने की अनुशंसा की जाती है।
NotificationCenter असंबंधित घटकों के बीच मनमानी घटनाओं के लिए एक प्रसारण तंत्र है। KVO किसी विशिष्ट ऑब्जेक्ट की किसी विशिष्ट संपत्ति में परिवर्तन देखता है। KVO को NSObject वंशानुक्रम की आवश्यकता होती है और setter के माध्यम से संपत्ति परिवर्तनों पर स्वचालित रूप से सूचित करता है। NotificationCenter केवल तभी सूचित करता है जब post स्पष्ट रूप से कॉल किया जाता है। मॉडल अवलोकन के लिए, KVO या Combine बेहतर है।
प्रति एप्लिकेशन प्रक्रिया एक default center। NotificationCenter() के माध्यम से अतिरिक्त केंद्र बनाए जा सकते हैं, लेकिन व्यवहार में साझा default का उपयोग किया जाता है। प्रत्येक केंद्र स्वतंत्र रूप से संचालित होता है — एक में post दूसरे के प्रेक्षकों को वितरित नहीं किया जाता है। मॉड्यूल अलगाव के लिए, रिवर्स-डोमेन सूचना नामों के माध्यम से अलग Name नामस्थानों का उपयोग करें।
आंशिक रूप से। Combine NotificationCenter.Publisher प्रदान करता है, जो NotificationCenter को एक रिएक्टिव स्ट्रीम में लपेटता है। Combine तुल्यकालिकता समस्या (receive(on:) के माध्यम से) को हल करता है, रूपांतरण ऑपरेटर जोड़ता है, और स्वचालित सदस्यता प्रबंधन (AnyCancellable) करता है। हालाँकि, NotificationCenter iOS सिस्टम सूचनाओं (UIApplication, UIKeyboard) और लीगेसी कोड के लिए बना हुआ है। Combine एक संवर्द्धन है, प्रतिस्थापन नहीं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें