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 सेट है या नहीं और संबंधित प्रोटोकॉल विधि को कॉल करता है। प्रत्यक्ष कॉल पर लाभ यह है कि प्रेषक 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 संदर्भ कैप्चर के साथ एक क्लोज़र का उपयोग करता है। चुनाव घटनाओं की संख्या, हस्ताक्षर जटिलता और वास्तुकला प्राथमिकताओं पर निर्भर करता है। 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 तालिका कोशिकाओं की उपस्थिति और व्यवहार का प्रबंधन करता है। इसमें पंक्ति चयन को संभालने, कोशिका ऊँचाई कॉन्फ़िगर करने, कस्टम हेडर/फ़ुटर दृश्य और स्वाइप क्रियाओं के लिए विधियाँ शामिल हैं। सभी प्रोटोकॉल विधियाँ वैकल्पिक हैं, जो केवल आवश्यक कार्यक्षमता को लागू करने की अनुमति देती हैं। प्रतिनिधि के बिना, तालिका डिफ़ॉल्ट सेटिंग्स के साथ काम करती है। ऐतिहासिक रूप से, delegate को 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 delegate के कारण retain cycle, delegate?.method() को कॉल करना भूल जाना, गलत प्रोटोकॉल विधि हस्ताक्षर, ऑपरेशन शुरू करने के बाद प्रतिनिधि सेट करना, और बहु-सूत्री टकराव। आइए प्रत्येक गलती और इसे रोकने के तरीके को देखें।
सबसे महत्वपूर्ण गलती delegate प्रॉपर्टी को weak var के बजाय strong var के रूप में घोषित करना है। यह एक retain cycle बनाता है जहाँ न तो प्रतिनिधि और न ही प्रतिनिधिमंडल देने वाला ऑब्जेक्ट मुक्त किया जा सकता है। परिणाम: मेमोरी लीक, ऐप धीमा होना, और छिपी हुई बग। समाधान: हमेशा delegate के लिए 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 एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें