Delegate ایک ڈیزائن پیٹرن ہے جس میں ایک آبجیکٹ پہلے سے طے شدہ طریقوں والے پروٹوکول کے ذریعے کسی دوسرے آبجیکٹ کو کاموں کی انجام دہی سونپتا ہے۔ iOS ڈیولپمنٹ میں، Delegate Cocoa Touch کے بنیادی پیٹرن میں سے ایک ہے، جو بھیجنے والے اور وصول کرنے والے کے درمیان براہ راست تعلق کے بغیر غیر متزامن اطلاع کے لیے استعمال ہوتا ہے۔ Apple Documentation (2025) کے مطابق، Foundation اور UIKit میں ٹیبل ایونٹس، نیٹ ورک کی درخواستوں اور مقام کے انتظام کو سنبھالنے کے لیے نمائندگی کا استعمال کیا جاتا ہے۔ یہ پیٹرن اجزاء کے ڈھیلے تعلق اور کوڈ کے دوبارہ استعمال کو یقینی بناتا ہے۔
اہم نکات
Delegate (مندوب) ایک آبجیکٹ ہے جو ایک مخصوص پروٹوکول کو لاگو کرتا ہے اور کسی دوسرے آبجیکٹ کے ایونٹس کے بارے میں اطلاعات وصول کرتا ہے۔ نمائندگی کا پیٹرن وراثت کا ایک متبادل ہے: طریقوں کو اوور رائیڈ کرنے کے لیے ذیلی کلاس بنانے کے بجائے، ایک آبجیکٹ ایونٹ ہینڈلنگ کو کسی بیرونی آبجیکٹ کو سونپتا ہے۔ iOS میں، نمائندگی لازمی اور اختیاری طریقوں کے ساتھ Swift پروٹوکول کے ذریعے لاگو کی جاتی ہے۔ delegate پراپرٹی ہمیشہ weak var کے طور پر اعلان کی جاتی ہے تاکہ آبجیکٹس کے درمیان چکری حوالوں سے بچا جا سکے۔
ایک delegate پروٹوکول آبجیکٹس کے درمیان تعامل کا معاہدہ وضع کرتا ہے۔ لازمی طریقے مندوب کے ذریعے لاگو کیے جانے چاہئیں، ورنہ کوڈ مرتب نہیں ہوگا۔ اختیاری طریقے @objc optional وصف سے نشان زد ہوتے ہیں اور مندوب کو صرف متعلقہ ایونٹس پر ردعمل ظاہر کرنے کی اجازت دیتے ہیں۔ طریقوں کے نام ایک کنونشن کی پیروی کرتے ہیں: پہلا پیرامیٹر بھیجنے والا آبجیکٹ ہے، دوسرا ایونٹ کا ڈیٹا ہے۔ مثال کے طور پر، tableView(_:didSelectRowAt:) اس بات کی نشاندہی کرتا ہے کہ بھیجنے والا UITableView ہے اور ڈیٹا منتخب قطار کا اشاریہ ہے۔
// Delegate پروٹوکول
protocol DownloadManagerDelegate: AnyObject {
func downloadManager(_ manager: DownloadManager,
didFinishWith data: Data)
func downloadManager(_ manager: DownloadManager,
didFailWith error: Error)
@objc optional func downloadManager(_ manager: DownloadManager,
didUpdateProgress progress: Float)
}
// Delegate استعمال کرنے والی کلاس
class DownloadManager {
weak var delegate: DownloadManagerDelegate?
func startDownload(from url: URL) {
URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
guard let self else { return }
if let error = error {
self.delegate?.downloadManager(self, didFailWith: error)
} else if let data = data {
self.delegate?.downloadManager(self, didFinishWith: data)
}
}.resume()
}
}
delegate پراپرٹی کو retain cycle کو روکنے کے لیے weak var کے طور پر اعلان کیا جانا چاہیے۔ اگر حوالہ مضبوط ہوتا، تو مندوب اور نمائندگی دینے والا آبجیکٹ ایک دوسرے کو پکڑے رہتے، اور ARC ان کی میموری کو آزاد نہیں کر سکتا تھا۔ delegate پروٹوکول AnyObject (صرف کلاسز) سے وراثت پاتے ہیں، جو weak کے استعمال کی اجازت دیتا ہے۔ ڈھانچے اور شمارندی اقسام قدر کی معنویات کی وجہ سے مندوب نہیں ہو سکتے۔ قدر کی اقسام کے لیے متبادل callback closures ہیں۔
class ViewController: DownloadManagerDelegate {
let manager = DownloadManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self // weak — کوئی retain cycle نہیں
manager.startDownload(from: url)
}
func downloadManager(_ manager: DownloadManager, didFinishWith data: Data) {
processData(data)
}
func downloadManager(_ manager: DownloadManager, didFailWith error: Error) {
showError(error)
}
}
Delegate پیٹرن ایک سے ایک کی بنیاد پر کام کرتا ہے: ایک بھیجنے والا آبجیکٹ کسی خاص وقت پر صرف ایک delegate رکھ سکتا ہے۔ جب کوئی ایونٹ ہوتا ہے، بھیجنے والا چیک کرتا ہے کہ آیا delegate مقرر ہے اور متعلقہ پروٹوکول طریقہ کو کال کرتا ہے۔ براہ راست کالوں پر فائدہ یہ ہے کہ بھیجنے والا مندوب کی قسم نہیں جانتا، صرف یہ جانتا ہے کہ وہ پروٹوکول کی تعمیل کرتا ہے۔ یہ SOLID سے انحصار الٹاؤں کے اصول (DIP) کی تعمیل کرتا ہے۔
مندوب تفویض کے ذریعے مقرر کیا جاتا ہے: someObject.delegate = self۔ جب مندوب کی ڈی لوکیشن ہوتی ہے، weak معنویات کی وجہ سے پراپرٹی خود بخود nil ہو جاتی ہے۔ مندوب کے طریقہ کو کال کرنے سے پہلے، اختیاری زنجیر کے ذریعے مندوب کی جانچ کی جاتی ہے: delegate?.method()۔ اگر delegate nil ہے تو کال کو بغیر کریش کے نظر انداز کر دیا جاتا ہے۔ اختیاری پروٹوکول طریقوں کے لیے، ایک اضافی جانچ استعمال کی جاتی ہے: delegate?.responds(to: #selector(...))، اگرچہ Swift میں یہ جانچ عام طور پر اختیاری طریقہ کے اعلان کے ذریعے مضمر ہوتی ہے۔
ملٹی تھریڈ والے ماحول میں، delegate غیر متزامن نتائج کی واپسی کے لیے استعمال ہوتا ہے۔ URLSession ڈیٹا موصول ہونے، ٹائم آؤٹ یا تصدیقی غلطی پر کال کیے جانے والے طریقوں کے ساتھ URLSessionDelegate فراہم کرتا ہے۔ مندوب کے طریقے URLSession کے بیک گراؤنڈ قطار میں انجام پاتے ہیں، لہذا UI اپ ڈیٹس کے لیے مرکزی قطار پر بھیجنا ضروری ہے۔ غیر متزامن delegate کال کرنے والے تھریڈ کو مسدود نہیں کرتا، جس سے دیگر کام جاری رہ سکتے ہیں۔
class NetworkService: NSObject, URLSessionDataDelegate {
private lazy var session = URLSession(
configuration: .default,
delegate: self,
delegateQueue: OperationQueue()
)
private var receivedData = Data()
func urlSession(_ session: URLSession,
dataTask: URLSessionDataTask,
didReceive data: Data) {
receivedData.append(data)
let progress = Float(receivedData.count) / Float(expectedSize)
DispatchQueue.main.async {
self.progressHandler?(progress)
}
}
func urlSession(_ session: URLSession,
task: URLSessionTask,
didCompleteWithError error: Error?) {
if let error = error {
delegate?.networkService(self, didFailWith: error)
} else {
delegate?.networkService(self, didReceive: receivedData)
}
}
}
Delegate اور Callback ایک ہی مسئلہ — غیر متزامن اطلاع — کو حل کرتے ہیں، لیکن مختلف طریقوں سے۔ Delegate نامزد طریقوں کے ساتھ ایک پروٹوکول استعمال کرتا ہے، Callback سیاق و سباق کی گرفت کے ساتھ ایک بندش (closure) استعمال کرتا ہے۔ انتخاب کا انحصار ایونٹس کی تعداد، دستخطوں کی پیچیدگی اور تعمیراتی ترجیحات پر ہے۔ Apple متعدد ایونٹس والے APIs کے لیے Delegate (UITableView — 20+ طریقے) اور ایک بار کی تکمیل کے لیے Callback تجویز کرتا ہے۔
Delegate ایک ذریعہ سے متعدد مختلف ایونٹس کو سنبھالتے وقت افضل ہے۔ مثال کے طور پر، CLLocationManager اپنے مندوب کو مقام کی تبدیلیوں، اجازت کی غلطیوں، جغرافیائی حدود میں داخلے/باہر نکلنے اور خدمت کی حیثیت کی تبدیلیوں کے بارے میں آگاہ کرتا ہے۔ ہر ایونٹ ایک واضح نام اور ٹائپ کردہ پیرامیٹرز کے ساتھ ایک علیحدہ پروٹوکول طریقہ ہے۔ Delegate رویے کی ترتیب (should، will، did طریقے) کے لیے بھی آسان ہے۔
Callback ایک نتیجے والی ایک بار کی درخواستوں کے لیے آسان ہے۔ URLSession.dataTask میں Completion handler کال کی جگہ پر کم از کم تین پروٹوکول طریقوں کے مقابلے میں ایک لائن لیتا ہے۔ Callback فعالی زنجیروں (map، flatMap، async/await) کے لیے بھی زیادہ فطری ہے۔ تاہم، 2-3 سطحوں سے زیادہ گھرلاو پر، Callback Callback Hell میں بدل جاتا ہے، جبکہ Delegate ہمیشہ چپٹا رہتا ہے۔
iOS SDK میں مختلف ذیلی نظاموں کے لیے درجنوں بلٹ ان delegate پروٹوکول ہیں۔ ہر ایک ایک مخصوص تعامل کے منظر نامے کے لیے ڈیزائن کیا گیا ہے۔ Apple Documentation (2025) کے مطابق، سب سے زیادہ استعمال ہونے والے مندوب UITableViewDelegate، UITextFieldDelegate، CLLocationManagerDelegate، URLSessionDelegate اور UNUserNotificationCenterDelegate ہیں۔ ان پروٹوکولز میں ضرورت کی مختلف سطحوں کے ساتھ 3 سے 30 طریقے ہوتے ہیں۔
UITableViewDelegate ٹیبل سیلز کی ظاہری شکل اور رویے کا انتظام کرتا ہے۔ اس میں قطار کے انتخاب کو سنبھالنے، سیل کی اونچائی ترتیب دینے، حسب ضرورش سر/پیر کے نظارے اور سوائپ ایکشنز کے لیے طریقے شامل ہیں۔ تمام پروٹوکول طریقے اختیاری ہیں، جس سے صرف ضروری فعالیت کو لاگو کیا جا سکتا ہے۔ مندوب کے بغیر، ٹیبل ڈیفالٹ سیٹنگز کے ساتھ کام کرتی ہے۔ تاریخی طور پر، مندوب کو UITableViewDataSource کے ساتھ ملایا جاتا تھا۔
URLSessionDelegate HTTP درخواستوں پر تفصیلی کنٹرول فراہم کرتا ہے۔ مندوب کے طریقے سرور کا جواب موصول ہونے، ڈیٹا آنے یا ڈاؤن لوڈ مکمل ہونے پر کال کیے جاتے ہیں۔ مخصوص کام کی اقسام کے لیے بنیادی فعالیت کو بڑھانے والے خصوصی ذیلی پروٹوکول URLSessionTaskDelegate اور URLSessionDataDelegate ہیں۔ بیک گراؤنڈ ڈاؤن لوڈز، SSL سرٹیفکیٹس اور حسب ضرور ری ڈائریکٹ ہینڈلنگ کی حمایت کے لیے مندوب ضروری ہے۔
| Delegate | طریقے | مقصد |
|---|---|---|
| UITableViewDelegate | 25 | ٹیبل کی ظاہری شکل اور تعامل |
| UITextFieldDelegate | 8 | متن کا اندراج اور کی بورڈ ہینڈلنگ |
| CLLocationManagerDelegate | 12 | مقام کی تازہ کاری اور جغرافیائی حدود |
| URLSessionDelegate | 6 | HTTP سیشن اور سرٹیفکیٹ کا انتظام |
| UNUserNotificationCenterDelegate | 4 | پیش منظر میں پش اطلاع ہینڈلنگ |
میموری کا انتظام iOS میں delegate کے ساتھ کام کرنے کا ایک اہم پہلو ہے۔ ARC (خودکار حوالہ گنتی) خود بخود میموری کا انتظام کرتا ہے، لیکن صرف weak/unowned حوالوں کے صحیح استعمال سے۔ قواعد کی خلاف ورزی میموری کے رساو یا قبل از وقت ڈی لوکیشن کا باعث بنتی ہے۔ strong کے طور پر اعلان کردہ مندوب ایک retain cycle تشکیل دیتا ہے اگر مندوب کا مالک نمائندگی دینے والے آبجیکٹ کا بھی حوالہ رکھتا ہے۔
Retain cycle اس وقت ہوتا ہے جب آبجیکٹ A (مالک) خود کو آبجیکٹ B کا مندوب مقرر کرتا ہے، اور B مندوب کے لیے ایک مضبوط حوالہ رکھتا ہے۔ مثال: ViewController URLSession بناتا ہے، خود کو سیشن کا مندوب مقرر کرتا ہے، لیکن URLSession ڈیفالٹ طور پر مندوب کے لیے ایک مضبوط حوالہ رکھتا ہے اگر delegateQueue متعین نہ ہو۔ حل یہ ہے کہ مندوب کے حوالہ کی قسم (weak یا strong) کے لیے API دستاویزات کو ہمیشہ چیک کریں اور deinit میں مندوب کو واضح طور پر nil کریں۔
class SafeViewController: UIViewController {
private var session: URLSession?
private var service: NetworkService?
override func viewDidLoad() {
super.viewDidLoad()
service = NetworkService()
service?.delegate = self
}
deinit {
// deinit میں delegate کو nil کریں — best practice
service?.delegate = nil
session?.invalidateAndCancel()
}
}
// NSObject کے ذریعے weak delegate کے ساتھ URLSession
class WeakDelegateSession: NSObject {
private weak var delegate: URLSessionDelegate?
func createSession() -> URLSession {
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
return URLSession(
configuration: .default,
delegate: self,
delegateQueue: queue
)
}
}
مندوب کے طریقہ کو کال کرنے سے پہلے، آپ کو تصدیق کرنی چاہیے کہ مندوب موجود ہے (nil نہیں) اور کال کردہ طریقہ کو لاگو کرتا ہے۔ لازمی پروٹوکول طریقوں کے لیے، کسی جانچ کی ضرورت نہیں — مرتب کرنے والا نفاذ کی ضمانت دیتا ہے۔ اختیاری طریقوں کے لیے، respond(to:) یا اختیاری زنجیر استعمال کریں۔ اگر مندوب کی ڈی لوکیشن ہو جاتی ہے، تو weak حوالہ خود بخود nil ہو جاتا ہے، اور مندوب کی کال کو نظر انداز کر دیا جاتا ہے۔ یہ محفوظ رویہ ہے جس میں اضافی ہینڈلنگ کی ضرورت نہیں ہے۔
ڈیولپرز اکثر Delegate پیٹرن کے ساتھ کام کرتے وقت غلطیاں کرتے ہیں، خاص طور پر iOS سیکھنے کے ابتدائی مراحل میں۔ سب سے عام میں شامل ہیں: strong مندوب کی وجہ سے retain cycle، delegate?.method() کو کال کرنا بھول جانا، غلط پروٹوکول طریقہ کے دستخط، آپریشن شروع کرنے کے بعد مندوب مقرر کرنا اور ملٹی تھریڈنگ تصادم۔ آئیے ہر غلطی اور اسے روکنے کا طریقہ دیکھتے ہیں۔
سب سے اہم غلطی delegate پراپرٹی کو weak var کی بجائے strong var کے طور پر اعلان کرنا ہے۔ یہ ایک retain cycle تشکیل دیتا ہے جہاں نہ تو مندوب اور نہ ہی نمائندگی دینے والا آبجیکٹ آزاد ہو سکتا ہے۔ نتائج: میموری کا رساو، ایپ کی سست روی اور پوشیدہ بگز۔ حل: مندوب کے لیے ہمیشہ weak var استعمال کریں، اور پروٹوکول کو AnyObject سے وراثت دلوائیں تاکہ قدر کی اقسام کو مندوب کے طور پر استعمال کرنے سے روکا جا سکے۔
اگر غیر متزامن طریقہ کو کال کرنے کے بعد مندوب مقرر کیا جاتا ہے، تو پہلے ایونٹس ضائع ہو سکتے ہیں۔ مثال: manager.delegate = self تفویض کرنے سے پہلے startDownload() کال کرنا مکمل ہونے کے کال بیک سے محروم کر دیتا ہے اگر ڈاؤن لوڈ ہم وقت یا بہت تیزی سے انجام پائے۔ حل: غیر متزامن طریقہ کو کال کرنے سے پہلے مندوب مقرر کریں اور پروٹوکول تبصروں میں ابتدائی ترتیب کو دستاویز کریں۔
اکثر پوچھے گئے سوالات
Weak مندوب اور نمائندگی دینے والے آبجیکٹ کے درمیان retain cycle کو روکتا ہے۔ اگر حوالہ مضبوط ہوتا، تو آبجیکٹ ایک دوسرے کو پکڑے رہتے اور ARC انہیں آزاد نہیں کر سکتا تھا۔ ایک weak حوالہ مندوب کی ڈی لوکیشن پر خود بخود nil ہو جاتا ہے۔ یہ Objective-C کے ظہور کے بعد سے ایک معیاری Cocoa Touch عمل ہے اور پسماندہ مطابقت کے لیے Swift میں محفوظ کیا گیا ہے۔
Delegate ایونٹس کو سنبھالتا ہے اور رویے کا انتظام کرتا ہے (سیل کی اونچائی، ٹیپ پر ردعمل)۔ DataSource ڈسپلے کے لیے ڈیٹا فراہم کرتا ہے (قطاروں کی تعداد، سیل)۔ مندوب “کیسے؟” سوال کا جواب دیتا ہے، dataSource “کیا؟” سوال کا جواب دیتا ہے۔ iOS میں، دونوں پروٹوکول کے ذریعے لاگو کیے جاتے ہیں، اکثر ایک ہی کنٹرولر میں، لیکن تصوراتی طور پر الگ ہیں۔
نہیں، اگر پروٹوکول AnyObject (کلاس پروٹوکول) سے وراثت پاتا ہے۔ weak حوالہ جات صرف حوالہ کی اقسام (کلاسز) کے لیے دستیاب ہیں۔ قدر کی اقسام (struct، enum) کے لیے، callback closures یا علیحدہ ریپر کلاس استعمال کریں۔ اگر آپ پروٹوکول کو کنٹرول کرتے ہیں، تو آپ AnyObject سے وراثت سے بچ سکتے ہیں، لیکن پھر weak ممنوع ہے — شعوری طور پر weak مندوب اور struct مندوب کے درمیان انتخاب کریں۔
responds(to:) ایک NSObjectProtocol طریقہ ہے جو چیک کرتا ہے کہ آیا کوئی آبجیکٹ مخصوص سلیکٹر کو لاگو کرتا ہے۔ یہ کال کرنے سے پہلے اختیاری @objc پروٹوکول طریقوں کو چیک کرنے کے لیے استعمال ہوتا ہے۔ اس چیک کے بغیر، ایک غیر لاگو کردہ اختیاری طریقہ کو کال کرنا NSInvalidArgumentException کا سبب بنے گا۔ Swift میں، @objc optional والے پروٹوکول کے لیے، چیک اختیاری بائنڈنگ کے ذریعے مضمر ہو سکتا ہے۔
نہیں، delegate ایک نمائندگی کا پیٹرن ہے، سنگلٹن نہیں۔ سنگلٹن کے برعکس، ایک مندوب کو رن ٹائم پر تبدیل کیا جا سکتا ہے اور ہر نمائندگی دینے والے آبجیکٹ کے لیے ایک مثال میں موجود ہوتا ہے۔ ایک آبجیکٹ متعدد بھیجنے والوں کے لیے مندوب ہو سکتا ہے۔ سنگلٹن ایک تخلیقی پیٹرن ہے جو ایک کلاس مثال کی ضمانت دیتا ہے، جس کا نمائندگی سے کوئی تعلق نہیں ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں