Weak Reference (कमज़ोर संदर्भ) एक ऑब्जेक्ट का संदर्भ है जो ARC में उसके रिटेन काउंट को नहीं बढ़ाता है। Apple Swift Language Guide, 2026 के अनुसार, weak संदर्भ weak कीवर्ड से घोषित किए जाते हैं और हमेशा वैकल्पिक होते हैं। जब ऑब्जेक्ट मुक्त होता है, तो उसके सभी weak संदर्भ स्वचालित रूप से nil पर सेट हो जाते हैं, जो डैंगलिंग पॉइंटर्स को रोकता है और weak संदर्भों को रिटेन साइकिल तोड़ने के लिए एक सुरक्षित तंत्र बनाता है।
मुख्य बातें
weak कीवर्ड; प्रकार हमेशा वैकल्पिक (?)Weak Reference ARC (Automatic Reference Counting) में एक ऑब्जेक्ट का गैर-मालिकाना संदर्भ है। एक मजबूत संदर्भ के विपरीत, जो ऑब्जेक्ट के रिटेन काउंट को बढ़ाता है और उसके जीवनकाल की गारंटी देता है, एक कमज़ोर संदर्भ ऑब्जेक्ट को मुक्त होने देता है भले ही उसका अभी भी संदर्भ लिया जा रहा हो। डीलोकेशन के बाद, कमज़ोर संदर्भ स्वचालित रूप से nil पर सेट हो जाता है — इसे ज़ीरोइंग weak कहा जाता है।
ज़ीरोइंग weak Swift और Objective-C runtime की एक प्रमुख विशेषता है। जब किसी ऑब्जेक्ट का रेफरेंस काउंट शून्य तक पहुँचता है और ऑब्जेक्ट डीलोकेट होता है, runtime इस ऑब्जेक्ट के सभी weak संदर्भों (एक विशेष weak तालिका में संग्रहीत) को पार करता है और उन्हें nil पर सेट करता है। यह सुनिश्चित करता है कि weak संदर्भों के माध्यम से मुक्त मेमोरी तक पहुँच (use-after-free) असंभव है — कोई भी पढ़ने की क्रिया nil लौटाती है।
Apple WWDC 2012 Session 406 के अनुसार, ज़ीरोइंग weak संदर्भों ने डैंगलिंग पॉइंटर्स से संबंधित क्रैश बग्स की एक पूरी श्रेणी को समाप्त कर दिया, जो मैन्युअल मेमोरी प्रबंधन (MRR) में आम थे। MRR में, weak संदर्भ केवल __unsafe_unretained के रूप में मौजूद थे — वे शून्य नहीं होते थे, और डीलोकेटेड ऑब्जेक्ट तक पहुँच EXC_BAD_ACCESS का कारण बनती थी।
आइए Apple पारिस्थितिकी तंत्र की दोनों भाषाओं में weak संदर्भ घोषित करने के सिंटैक्स को देखें। साझा runtime के बावजूद, सिंटैक्स अलग है, लेकिन अर्थ विज्ञान समान है।
Swift में, weak संदर्भ var से पहले weak कीवर्ड के साथ घोषित किए जाते हैं। प्रकार हमेशा वैकल्पिक (Type?) होना चाहिए, क्योंकि संदर्भ किसी भी समय nil हो सकता है। स्थिरांक (let) weak नहीं हो सकते — केवल चर।
class ViewController: UIViewController {
// weak properties: only var, only optional
weak var delegate: ViewControllerDelegate?
weak var parentView: UIView?
weak var completionHandler: ((Bool) -> Void)? // ⚠️ क्लोज़र weak संग्रहीत नहीं करते
// ⬆️ त्रुटि: weak केवल class प्रकारों पर लागू किया जा सकता है, closures पर नहीं
}
महत्वपूर्ण: weak केवल class इंस्टेंस (class प्रकार), AnyObject, और AnyObject से प्राप्त प्रोटोकॉल पर लागू होता है। Struct, enum और क्लोज़र weak नहीं हो सकते — वे मूल्य प्रकार हैं और ARC में भाग नहीं लेते हैं।
Objective-C में, weak गुण __weak विशेषता या property घोषणा में weak संशोधक के माध्यम से घोषित किए जाते हैं:
// Objective-C: weak property
@interface MyViewController : UIViewController
@property (weak, nonatomic) id<MyDelegate> delegate;
@end
// स्थानीय weak चर
__weak MyObject *weakRef = someStrongObject;
Objective-C runtime भी ज़ीरोइंग weak प्रदान करता है, लेकिन अतिरिक्त रूप से C संरचनाओं और कुछ Core Foundation ऑब्जेक्ट्स के साथ weak के उपयोग को अवरुद्ध करता है। इनके लिए, __unsafe_unretained का उपयोग किया जाता है — बिना ज़ीरोइंग के।
कमज़ोर संदर्भ एक सार्वभौमिक समाधान नहीं हैं, बल्कि विशिष्ट परिदृश्यों के लिए एक उपकरण हैं। हर जगह weak का उपयोग करने से अनावश्यक जटिलता आती है और पढ़ने योग्यता ख़राब होती है। आइए सही उपयोग परिदृश्यों को देखें।
डेलीगेट्स — weak के लिए प्राथमिक परिदृश्य। मालिकाना ऑब्जेक्ट (जैसे UITableView) अपने आप में एक मजबूत संदर्भ रखता है, जबकि डेलीगेट (UIViewController) को तालिका का मालिक नहीं होना चाहिए। Apple SDK गारंटी देता है कि सभी डेलीगेट और dataSource weak हैं। अपने स्वयं के प्रोटोकॉल के लिए, हमेशा weak var delegate का उपयोग करें।
जब किसी बाल ऑब्जेक्ट को अपने माता-पिता को संदर्भित करने की आवश्यकता होती है (जैसे ChildViewController कोऑर्डिनेटर तक पहुँच), तो weak संदर्भ का उपयोग करें। माता-पिता बच्चे का मालिक है (strong), बच्चा माता-पिता का निरीक्षण करता है (weak) — रिटेन साइकिल समाप्त हो जाती है।
Capture list [weak self] — class गुणों के रूप में संग्रहीत क्लोज़र्स में रिटेन साइकिल से बचने का मानक तरीका। यदि self क्लोज़र पूरा होने से पहले डीलोकेट हो सकता है, तो weak self अनिवार्य है।
| परिदृश्य | Weak | Strong |
|---|---|---|
| डेलीगेट | ✅ हमेशा weak | ❌ रिटेन साइकिल |
| माता-पिता → बच्चा | ❌ आवश्यक नहीं (माता-पिता को मालिक होना चाहिए) | ✅ Strong |
| बच्चा → माता-पिता | ✅ Weak | ❌ रिटेन साइकिल |
| अतुल्यकालिक कॉलबैक | ✅ [weak self] | ❌ रिटेन साइकिल जोखिम |
| मजबूत युग्मन (owned) | ❌ unowned | ✅ Strong |
सामान्य नियम: यदि ऑब्जेक्ट A, B का मालिक है (A → B strong), तो B → A weak या unowned होना चाहिए। मजबूत संदर्भों की दिशा हमेशा मालिक से अधीनस्थ की ओर होनी चाहिए।
Weak और unowned दोनों रिटेन काउंट नहीं बढ़ाते हैं, लेकिन ऑब्जेक्ट डीलोकेशन के बाद व्यवहार में भिन्न होते हैं। उनके बीच चुनाव जीवनकाल गारंटी का मामला है।
Weak: स्वचालित रूप से nil हो जाता है, प्रकार हमेशा वैकल्पिक, उपयोग से पहले अनरैप की आवश्यकता। सुरक्षित — nil तक पहुँच क्रैश का कारण नहीं बनती।
Unowned: nil नहीं होता, प्रकार गैर-वैकल्पिक। यदि ऑब्जेक्ट डीलोकेट हो जाता है, तो unowned संदर्भ एक डैंगलिंग पॉइंटर बन जाता है — उस तक पहुँच runtime क्रैश का कारण बनती है। Unowned मानता है कि ऑब्जेक्ट संदर्भित पक्ष से कम से कम उतने ही समय तक जीवित रहता है।
Weak चुनें यदि: ऑब्जेक्ट किसी भी समय डीलोकेट हो सकता है (स्क्रीन बंद होने के बाद डेलीगेट), आप ऑब्जेक्ट के जीवनकाल को नियंत्रित नहीं करते, या गारंटी के बारे में अनिश्चित हैं। Weak सार्वभौमिक सुरक्षित विकल्प है।
Unowned चुनें यदि: ऑब्जेक्ट गारंटीकृत है कि संदर्भित ऑब्जेक्ट से पहले डीलोकेट नहीं होगा (जैसे Customer → CreditCard, जहाँ कार्ड ग्राहक के बिना मौजूद नहीं है)। Unowned बिना अनरैप के एक गैर-वैकल्पिक API प्रदान करता है, जो कोड में अधिक सुविधाजनक है।
class Order {
let id: Int
var items: [Item] = []
init(id: Int) { self.id = id }
// मजबूत संबंध: Order, Item का मालिक है
func addItem(name: String) {
let item = Item(name: name, order: self)
items.append(item)
}
}
class Item {
let name: String
unowned let order: Order // ✅ unowned — Item, Order के बिना नहीं रहता
init(name: String, order: Order) {
self.name = name
self.order = order
}
}
// weak के साथ उदाहरण: जीवनकाल गारंटी के बिना डेलीगेट
protocol NetworkServiceDelegate: AnyObject {
func didReceiveResponse(data: Data)
}
class NetworkService {
weak var delegate: NetworkServiceDelegate? // ✅ weak — डेलीगेट जा सकता है
}
उदाहरण में, Item unowned का उपयोग करता है क्योंकि एक ऑर्डर आइटम ऑर्डर के बिना मौजूद नहीं हो सकता — जीवनकाल की गारंटी अटल है। NetworkService weak का उपयोग करता है क्योंकि डेलीगेट (जैसे ViewController) किसी भी समय बंद और डीलोकेट हो सकता है।
कमज़ोर संदर्भ एक शक्तिशाली उपकरण हैं, लेकिन उनमें सीमाएँ हैं जिन्हें iOS डेवलपमेंट में सही उपयोग के लिए समझना महत्वपूर्ण है।
कमज़ोर संदर्भ मजबूत संदर्भों की तुलना में धीमे होते हैं: प्रत्येक पहुँच पर, runtime जाँचता है कि ऑब्जेक्ट डीलोकेट हुआ है या नहीं (weak तालिका में lookup)। अधिकांश परिदृश्यों में, अंतर अगोचर है, लेकिन लाखों पहुँच वाले हॉट लूप्स में, weak एक अड़चन बन सकता है। उच्च-लोड परिदृश्यों के लिए, strong का उपयोग करें और आर्किटेक्चर को पुनर्व्यवस्थित करें।
Struct, enum, tuple — मूल्य प्रकार जो ARC में भाग नहीं लेते हैं। weak struct घोषित करने का प्रयास संकलन त्रुटि का कारण बनता है। मूल्य प्रकार के लिए कमज़ोर संदर्भ संग्रहीत करने के लिए, class प्रकार या क्लोज़र में रैपर का उपयोग करें।
ज़ीरोइंग weak थ्रेड-सुरक्षित है: यदि कोई ऑब्जेक्ट एक थ्रेड पर डीलोकेट होता है, तो weak संदर्भ सभी थ्रेड्स पर परमाणु रूप से शून्य हो जाता है। हालांकि, weak संदर्भ को पढ़ने और उसे डीरेफरेंस करने के बीच की खिड़की रेस कंडीशन का कारण बन सकती है — weak संदर्भ प्राप्त करने और उसके उपयोग के बीच ऑब्जेक्ट डीलोकेट हो जाता है। समाधान: स्थानीय चर में weak संदर्भ का strong कैप्चर।
// मल्टीथ्रेडिंग में weak के साथ रेस कंडीशन
func performAsync() {
weak var weakSelf = self
queue.async {
// ⚠️ weakSelf जाँच और उपयोग के बीच nil हो सकता है
if weakSelf != nil {
weakSelf!.doSomething() // CRASH यदि nil हो जाता है
}
}
}
// ✅ सुधार: उपयोग के दौरान strong कैप्चर
func performAsyncSafe() {
queue.async { [weak self] in
guard let strongSelf = self else { return }
strongSelf.doSomething() // strongSelf — स्थानीय strong संदर्भ
}
}
सुरक्षित संस्करण में, weak self को कैप्चर किया जाता है, फिर तुरंत एक स्थानीय strong चर strongSelf में अनरैप किया जाता है। यदि self अभी भी जीवित है, तो यह ब्लॉक की अवधि के लिए जीवित रहेगा। यदि नहीं, तो guard सक्रिय होता है और कोड निष्पादित नहीं होता है। यह मुहावरा Swift में अतुल्यकालिक क्लोज़र्स के लिए मानक पैटर्न है।
IBOutlet Interface Builder में weak होना चाहिए क्योंकि व्यू पदानुक्रम पहले से ही subview पर एक मजबूत संदर्भ रखता है। कंट्रोलर में मजबूत संदर्भ की नकल रिटेन साइकिल नहीं बनाती लेकिन अतिरिक्त है। आउटलेट के लिए कमज़ोर संदर्भ Apple की सिफारिश है, हालाँकि कई डेवलपर्स कोड सरलीकरण के लिए strong का उपयोग करते हैं।
अक्सर पूछे जाने वाले प्रश्न
नहीं, weak केवल मौजूदा ऑब्जेक्ट या nil को इंगित कर सकता है। एक नया ऑब्जेक्ट बनाते समय, आप पहले एक मजबूत संदर्भ प्राप्त करते हैं (इनिशियलाइज़र के माध्यम से), और उसके बाद ही आप एक कमज़ोर संदर्भ निर्दिष्ट कर सकते हैं। शुरुआत में weak nil एक सामान्य स्थिति है।
Weak ARC पर आधारित है, जो केवल संदर्भ प्रकारों (class) का प्रबंधन करता है। मूल्य प्रकार (struct, enum) असाइनमेंट पर कॉपी होते हैं और उनका रिटेन काउंट नहीं होता है। मूल्य प्रकारों के साथ कमज़ोर संबंधों के लिए, class में weak गुण वाले रैपर या क्लोज़र का उपयोग करें।
weak संदर्भ तक प्रत्येक पहुँच runtime तालिका में lookup करती है। लाखों पुनरावृत्तियों वाले लूप में, यह मजबूत संदर्भ से 2–5 गुना धीमा हो सकता है। हॉट पथों के लिए, लूप से पहले weak को स्थानीय strong चर में कॉपी करें।
जब ऑब्जेक्ट के सभी मजबूत संदर्भ खो जाते हैं — दायरे के अंत में, किसी गुण को पुनर्निर्दिष्ट करने पर, या स्क्रीन बंद होने पर। मल्टीथ्रेडेड वातावरण में, यह कोड की दो पंक्तियों के बीच हो सकता है। हमेशा guard let या if let के माध्यम से weak संदर्भों की जाँच करें।
अर्थपूर्ण रूप से समान: दोनों ज़ीरोइंग weak प्रदान करते हैं। अंतर: Swift को वैकल्पिक प्रकार और var की आवश्यकता है, Objective-C property संशोधक का उपयोग करता है। Objective-C __unsafe_unretained का भी समर्थन करता है — बिना ज़ीरोइंग के कमज़ोर संदर्भ (डैंगलिंग पॉइंटर का जोखिम)।
सारांश
weak var + वैकल्पिक प्रकार; केवल class प्रकार और AnyObject प्रोटोकॉलहम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें