NotificationCenter — جوہر، کام کرنے کا اصول اور اطلاع کا فن تعمیر

مصنف: IT Sectr اشاعت: 2026-03-18 مطالعے کا وقت: 10 منٹ

NotificationCenter iOS میں ایپلیکیشن کے اجزاء کے درمیان بھیجنے والے اور وصول کرنے والے کے درمیان براہ راست تعلق کے بغیر اطلاعات بھیجنے اور وصول کرنے کا ایک نظامی طریقہ کار ہے۔ Observer پیٹرن پر مبنی، NotificationCenter اشیاء کو واقعات کو سبسکرائب کرنے اور ان پر غیر ہم وقتہ طور پر ردعمل ظاہر کرنے کی اجازت دیتا ہے۔ Apple Documentation (2025) کے مطابق، NSNotificationCenter post(name:object:) کے ذریعے ہم وقتہ اطلاع بھیجنے اور NotificationQueue کے ذریعے موخر بھیجنے دونوں کو سپورٹ کرتا ہے۔ اطلاع کا مرکز ایک ہی پروسیس کے اندر کام کرتا ہے اور ایپلیکیشن کی حدود کو عبور نہیں کرتا۔

اہم نکات

  • NotificationCenter — iOS اجزاء کے درمیان واقعات کے تبادلے کے لیے Observer پیٹرن کا نفاذ۔
  • addObserver کسی شے کو ایک مخصوص نام اور بھیجنے والی شے کے ساتھ اطلاعات کا سبسکرائب کرتا ہے۔
  • post(name:object:) تمام سبسکرائب شدہ نگرانوں کو ہم وقتہ طور پر ایک اطلاع بھیجتا ہے۔
  • removeObserver کو deinit میں کال کرنا لازمی ہے، ورنہ اطلاع بھیجنے پر کریش ہوتا ہے۔
  • NotificationQueue غیر ہم وقتہ ترسیل کے لیے اطلاعات کو موخر کرنے کی اجازت دیتا ہے۔

NotificationCenter کیا ہے؟

NotificationCenter (NSNotificationCenter) اشیاء کے درمیان کمزور طور پر منسلک مواصلات کو نافذ کرنے کے لیے ایک بلٹ ان iOS طریقہ کار ہے۔ Observer پیٹرن ایک شے (بھیجنے والے) کو ان کے براہ راست حوالہ کے بغیر متعدد دوسری اشیاء (نگرانوں) کو کسی واقعے کے بارے میں مطلع کرنے کی اجازت دیتا ہے۔ NotificationCenter تین اکائیوں کے ساتھ کام کرتا ہے: Notification.Name (اطلاع کا شناخت کنندہ)، Notification (ڈیٹا والا کنٹینر) اور NotificationCenter (ڈسپیچر)۔ ہر ایپلیکیشن میں ایک مشترکہ default center ہوتا ہے۔

NSNotification اور Notification.Name

Notification.Name ایک ڈھانچہ ہے جو اطلاع کی قسم کی شناخت کرتا ہے۔ extension Name: Notification.Name(“MyNotification”) کے ذریعے بنایا جاتا ہے۔ Notification ایک شے ہے جس میں name، object (بھیجنے والا) اور userInfo (ڈیٹا والی لغت) ہوتا ہے۔ نظام کی اطلاعات مستقل کے طور پر اعلان کی جاتی ہیں: UIApplication.didBecomeActiveNotification، UIResponder.keyboardWillShowNotification۔ حسب ضرورت اطلاعات کو ناموں کے تصادم سے بچنے کے لیے extension کے ذریعے گروپ کیا جانا چاہیے۔ نام ریورس ڈومین ہونے چاہئیں۔

swift
// حسب ضرورت اطلاعات کی تعریف
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)

ایک نگران addObserver(_:selector:name:object:) طریقہ کے ذریعے اطلاع کو سبسکرائب کرتا ہے۔ Selector وہ طریقہ ہے جو اطلاع موصول ہونے پر کال کیا جائے گا۔ object پیرامیٹر کسی مخصوص بھیجنے والے سے اطلاعات کو فلٹر کرنے کی اجازت دیتا ہے۔ اگر object nil ہے تو نگران کسی بھی بھیجنے والے سے مخصوص نام والی تمام اطلاعات وصول کرتا ہے۔ iOS 9 سے، addObserver کو block-based API کے لیے دستی ہٹانے کی ضرورت نہیں ہے، لیکن selector-based کو ابھی بھی removeObserver کی ضرورت ہے۔

swift
// اطلاع کو سبسکرائب کرنا (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 کیسے کام کرتا ہے؟

NotificationCenter ایک میپنگ ٹیبل (نام → نگرانوں کا سیٹ) ذخیرہ کرتا ہے۔ جب بھیجنے والا post(name:object:) کال کرتا ہے، اطلاع کا مرکز ہم وقتہ طور پر اس نام کو سبسکرائب کرنے والے تمام نگرانوں کو عبور کرتا ہے اور ان کے سلیکٹر یا بلاکس کال کرتا ہے۔ اہم خصوصیت: post تمام ہینڈلرز کے مکمل ہونے تک موجودہ تھریڈ کو بلاک کرتا ہے۔ اگر ہینڈلرز بھاری کارروائیاں کرتے ہیں تو یہ بھیجنے والے میں تاخیر کرتا ہے۔ NotificationQueue اطلاعات کی ترسیل میں تاخیر کرکے اس مسئلے کو حل کرتا ہے۔

ہم وقتہ بھیجنا (post)

post(name:object:userInfo:) طریقہ فوری طور پر تمام نگرانوں کو اطلاع بھیجتا ہے۔ کال ہم وقتہ ہے — post کے بعد کا کوڈ تمام ہینڈلرز کے مکمل ہونے کے بعد ہی عمل میں آتا ہے۔ نگرانوں کے بلائے جانے کا ترتیب ضمانت شدہ نہیں ہے اور لانچوں کے درمیان تبدیل ہو سکتا ہے۔ ترتیب وار پروسیسنگ کے لیے، coalescing کے ساتھ NotificationQueue استعمال کریں۔ اسی اطلاع کے ہینڈلر کے اندر post کال نہ کریں — اس سے لامتناہی تکرار ہوتی ہے۔

موخر بھیجنا (NotificationQueue)

NotificationQueue غیر ہم وقتہ ترسیل کے لیے اطلاعات کو قطار میں شامل کرتا ہے۔ یہ coalescing (یکساں اطلاعات کو ضم کرنا) اور ترسیل کی قطار کے انتخاب (asap، idle، modal) کو سپورٹ کرتا ہے۔ Coalescing بار بار ہونے والے واقعات (ڈاؤن لوڈ کی پیشرفت) کے لیے مفید ہے جب آپ کو صرف آخری قدر سے مطلع کرنے کی ضرورت ہوتی ہے۔ NotificationQueue فعال ہونے کے لیے رن لوپ استعمال کرتا ہے، لہذا یہ صرف فعال رن لوپ والے تھریڈز میں کام کرتا ہے۔

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

Notification بمقابلہ Delegate بمقابلہ KVO

iOS اشیاء کے درمیان مواصلات کے لیے تین اہم طریقہ کار فراہم کرتا ہے: NotificationCenter، Delegate اور KVO (Key-Value Observing)۔ ہر ایک اطلاع کے مسئلے کو حل کرتا ہے لیکن منسلکیت، کارکردگی اور قسم کی حفاظت میں مختلف سمجھوتوں کے ساتھ۔ طریقہ کار کا انتخاب ایک سے ایک یا ایک سے کئی تعلق اور ڈیٹا کی منتقلی کی ضرورت پر منحصر ہے۔

خصوصیتNotificationCenterDelegateKVO
منسلکیتکمزور (اطلاع کا نام)مضبوط (پروٹوکول)درمیانی (کلید)
تعلقایک سے کئیایک سے ایکایک سے کئی
قسم کی حفاظتکم (userInfo Dictionary کے طور پر)اعلی (پروٹوکول کے طریقے)درمیانی (Any?)
کارکردگیدرمیانی (جدول کو عبور کرنا)اعلی (براہ راست کال)کم (NSObject)
غیر ہم وقتیہم وقتہ (post بلاک کرتا ہے)بھیجنے والے کے تھریڈ میں ہم وقتہتبدیلی پر ہم وقتہ

NotificationCenter کب منتخب کریں

NotificationCenter ان واقعات کے لیے مثالی ہے جن پر متعدد آزاد اجزاء کو ردعمل دینا چاہیے۔ مثالیں: ایپلیکیشن سیٹنگز میں تبدیلیاں، صارف لاگ آؤٹ، پس منظر میں پش اطلاع موصول ہونا۔ NotificationCenter کمزور طور پر منسلک ماڈیولز (فیچر A کو فیچر B کے بارے میں نہیں جاننا چاہیے) کے لیے بھی موزوں ہے۔ خرابی قسم کی حفاظت کی کمی ہے: userInfo کی کنجیاں سٹرنگ ہیں، enum نہیں۔

Delegate یا KVO کب منتخب کریں

Delegate واضح معاہدے (tableView.delegate) والے ایک سے ایک تعلقات کے لیے انتخاب ہے۔ Delegate تیز تر اور اقسام کے لحاظ سے محفوظ ہے۔ KVO ماڈل کی کسی مخصوص خاصیت (isLoading، progress) میں تبدیلیوں کا مشاہدہ کرنے کے لیے انتخاب ہے۔ KVO کو NSObject سے وراثت کی ضرورت ہے اور ڈیبگنگ میں مشکلات پیدا کر سکتا ہے (جادوئی سٹرنگ کنجیاں)۔ جدید Swift میں، Combine اور async ترتیب تینوں طریقوں کی جگہ لے لیتے ہیں۔

AddObserver: ہم وقتہ اور غیر ہم وقتہ اطلاعات

addObserver طریقہ دو سبسکرپشن اقسام کو سپورٹ کرتا ہے: selector-based (روایتی) اور block-based (بندش کے ساتھ)۔ Selector-based کو @objc مطابقت اور دستی نگران ہٹانے کی ضرورت ہے۔ Block-based (iOS 9+) کیپچر لسٹ استعمال کرنے کی اجازت دیتا ہے اور مضبوط حوالوں کے بغیر بلاکس استعمال کرتے وقت OS کے ذریعے خودکار طور پر منظم کیا جاتا ہے۔ Block-based قطار کو بھی سپورٹ کرتا ہے — نگران مخصوص قطار میں اطلاع وصول کرتا ہے۔

selector پر مبنی addObserver

سیلیکٹر کے ذریعے سبسکرائب کرنے کا روایتی طریقہ۔ ہینڈلر کے طریقہ کو @objc سے نشان زد کیا جانا چاہیے اور ایک اختیاری Notification قبول کرنا چاہیے۔ فائدہ: کسی بھی کلاس کے ذریعے استعمال کیا جا سکتا ہے، بشمول میراثی Objective-C۔ نقصانات: سیلیکٹر کے لیے قسم کی حفاظت کا فقدان، سیلیکٹر کے نام میں ٹائپو کا خطرہ، deinit میں لازمی removeObserver۔ اگر نگران شے سے پہلے ہٹا دیا جاتا ہے تو ہینڈلر نہیں بلایا جائے گا۔

block پر مبنی addObserver

Block-based API ایک بندش قبول کرتا ہے جو اطلاع موصول ہونے پر عمل میں آتی ہے۔ queue پیرامیٹر یہ طے کرتا ہے کہ بلاک کس قطار میں چلتا ہے — UI اپ ڈیٹس کے لیے مرکزی قطار یا ڈیٹا پروسیسنگ کے لیے پس منظر کی قطار۔ واپسی کی قدر NSObjectProtocol نگران کو ہٹانے کے لیے استعمال ہوتی ہے: NotificationCenter.default.removeObserver(observer)۔ جدید Swift میں block-based کو ترجیح دی جاتی ہے۔

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

// خودکار ہٹانے کے ساتھ استعمال
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 میں نگران کو ہٹائیں۔

removeObserver کب کال کریں

Selector-based: ہمیشہ deinit میں NotificationCenter.default.removeObserver(self) کال کریں۔ اگر نگران متعدد اطلاعات کا سبسکرائب ہے تو آپ ایک بار میں سب (پیرامیٹر کے بغیر) یا نام سے مخصوص ایک کو ہٹا سکتے ہیں۔ Block-based: addObserver سے واپس کردہ ٹوکن کے ساتھ removeObserver کے ذریعے ہٹائیں۔ iOS 9+ پر block-based کے لیے، لیک نہیں ہوتا، لیکن کارکردگی کے لیے ہٹانا اب بھی تجویز کیا جاتا ہے: ڈی ایلوکیٹ شدہ نگران 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() { }
}

ٹوکن پیٹرن کے ذریعے کمزور حوالے

ٹوکن پیٹرن نگران کے انتظام کو خودکار بناتا ہے۔ سبسکرپشن پر، ایک ٹوکن شے (NSObjectProtocol) واپس کی جاتی ہے جو ڈی ایلوکیشن پر خود بخود نگران کو ہٹا دیتی ہے۔ NotificationTokenWrapper NotificationCenter اور نگران ٹوکن کا ایک کمزور حوالہ ذخیرہ کرتا ہے، deinit میں removeObserver کال کرتا ہے۔ یہ NotificationCenter کو Combine طریقہ کار کے قریب لاتا ہے، جہاں AnyCancellable سبسکرپشن لائف سائیکل کا انتظام کرتا ہے۔

ملٹی تھریڈ والے ماحول میں NotificationCenter

تھریڈ کی حفاظت: NotificationCenter ضمانت دیتا ہے کہ post کسی بھی تھریڈ سے کال کیا جا سکتا ہے، اور تمام نگران اسی تھریڈ پر اطلاع وصول کریں گے جہاں post کال کیا گیا تھا۔ یہ ملٹی تھریڈ ایپلیکیشنز کے لیے اہم ہے: اگر پس منظر کے تھریڈ سے اطلاع بھیجی جاتی ہے تو ہینڈلرز بھی پس منظر کے تھریڈ میں عمل میں آئیں گے۔ UI اپ ڈیٹس کے لیے، DispatchQueue.main.async کے ذریعے ہینڈلنگ کو مرکزی قطار میں بھیجیں۔

post اور addObserver کی تھریڈ حفاظت

NotificationCenter مختلف تھریڈز سے post اور addObserver کالز کے لیے تھریڈ محفوظ ہے۔ اندرونی ہم وقت سازی لاکنگ استعمال کرتی ہے، لہذا متعدد تھریڈز سے بار بار post مقابلہ پیدا کر سکتے ہیں۔ زیادہ بوجھ والے منظرناموں (1000 فائلوں کی ڈاؤن لوڈ پیشرفت) کے لیے، علیحدہ اطلاع قطار یا Combine پبلیشر استعمال کریں۔ postingStyle .now کے ساتھ NotificationQueue براہ راست post کے برابر ہے۔

Combine کے ذریعے غیر ہم وقتہ ترسیل

NotificationCenter NotificationCenter.default.publisher(for:object:) کے ذریعے Combine پبلیشر کو سپورٹ کرتا ہے۔ Publisher ہر اطلاع کو Combine واقعہ میں بدل دیتا ہے جسے map، filter، debounce اور throttle کے ذریعے تبدیل کیا جا سکتا ہے۔ یہ ہم وقتہ ترسیل کے مسئلے کو حل کرتا ہے: Combine مخصوص Scheduler پر اطلاعات کو غیر ہم وقتہ طور پر پروسیس کرتا ہے۔ NotificationCenter.publisher میراثی طریقہ کار اور جدید رد عمل پروگرامنگ کے درمیان ایک پل ہے۔

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

اکثر پوچھے گئے سوالات

کیا NotificationCenter تھریڈ محفوظ ہے؟

جی ہاں، 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 میں کیا فرق ہے؟

NotificationCenter غیر متعلقہ اجزاء کے درمیان صوابدیدی واقعات کے لیے ایک نشریاتی طریقہ کار ہے۔ KVO کسی مخصوص شے کی کسی مخصوص خاصیت میں تبدیلیوں کا مشاہدہ کرتا ہے۔ KVO کو NSObject وراثت کی ضرورت ہے اور setter کے ذریعے خاصیت میں تبدیلیوں پر خود بخود مطلع کرتا ہے۔ NotificationCenter صرف اس وقت مطلع کرتا ہے جب post واضح طور پر کال کیا جائے۔ ماڈل مشاہدے کے لیے، KVO یا Combine ترجیح دی جاتی ہے۔

ایک ایپلیکیشن میں کتنے NotificationCenter موجود ہیں؟

فی ایپلیکیشن پروسیس ایک default center۔ NotificationCenter() کے ذریعے اضافی مراکز بنائے جا سکتے ہیں، لیکن عملی طور پر مشترکہ default استعمال ہوتا ہے۔ ہر مرکز آزادانہ طور پر کام کرتا ہے — ایک میں post دوسرے کے نگرانوں تک نہیں پہنچایا جاتا۔ ماڈیول علیحدگی کے لیے، ریورس ڈومین اطلاع کے ناموں کے ذریعے علیحدہ Name نام کی جگہیں استعمال کریں۔

کیا Combine NotificationCenter کو بدل دیتا ہے؟

جزوی طور پر۔ Combine NotificationCenter.Publisher فراہم کرتا ہے، جو NotificationCenter کو ایک رد عمل کے دھارے میں لپیٹتا ہے۔ Combine ہم وقتی مسئلے (receive(on:) کے ذریعے) کو حل کرتا ہے، تبدیلی کے آپریٹرز اور خودکار سبسکرپشن مینجمنٹ (AnyCancellable) شامل کرتا ہے۔ تاہم، NotificationCenter iOS نظام کی اطلاعات (UIApplication، UIKeyboard) اور میراثی کوڈ کے لیے باقی ہے۔ Combine ایک بہتری ہے، تبدیلی نہیں۔

خلاصہ

  • NotificationCenter — iOS میں کمزور منسلک ایک سے کئی مواصلات کے لیے Observer پیٹرن کا نفاذ۔
  • post موجودہ تھریڈ میں تمام نگرانوں کو ہم وقتہ طور پر اطلاع بھیجتا ہے، بھیجنے والے کو بلاک کرتا ہے۔
  • addObserver selector-based (@objc کے ساتھ) اور block-based (کیپچر لسٹ اور قطار کے ساتھ) سبسکرپشن کو سپورٹ کرتا ہے۔
  • removeObserver selector-based سبسکرپشنز کے لیے deinit میں لازمی ہے، ورنہ کریش۔
  • NotificationQueue بار بار ہونے والے واقعات کے لیے coalescing کے ساتھ موخر ترسیل فراہم کرتا ہے۔
  • تھریڈ کی حفاظت کسی بھی تھریڈ سے آپریشن کو یقینی بناتی ہے، لیکن ہینڈلرز بھیجنے والے کے تھریڈ میں عمل میں آتے ہیں۔
  • محفوظ اور جدید سبسکرپشن مینجمنٹ کے لیے ٹوکن پیٹرن یا Combine پبلیشر استعمال کریں۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں