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 پر مبنی)
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 پر مبنی، 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 کی کنجیاں سٹرنگ ہیں، enum نہیں۔
Delegate واضح معاہدے (tableView.delegate) والے ایک سے ایک تعلقات کے لیے انتخاب ہے۔ Delegate تیز تر اور اقسام کے لحاظ سے محفوظ ہے۔ KVO ماڈل کی کسی مخصوص خاصیت (isLoading، progress) میں تبدیلیوں کا مشاہدہ کرنے کے لیے انتخاب ہے۔ KVO کو NSObject سے وراثت کی ضرورت ہے اور ڈیبگنگ میں مشکلات پیدا کر سکتا ہے (جادوئی سٹرنگ کنجیاں)۔ جدید Swift میں، Combine اور async ترتیب تینوں طریقوں کی جگہ لے لیتے ہیں۔
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 پبلیشر استعمال کریں۔ postingStyle .now کے ساتھ NotificationQueue براہ راست post کے برابر ہے۔
NotificationCenter NotificationCenter.default.publisher(for:object:) کے ذریعے Combine پبلیشر کو سپورٹ کرتا ہے۔ 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 پبلیشر بھی تھریڈ کے مسئلے کو حل کرتا ہے۔
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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں