defer Swift में एक नियंत्रण प्रवाह निर्माण है जो वर्तमान स्कोप से बाहर निकलने पर कोड के एक ब्लॉक के निष्पादन को शेड्यूल करता है। defer ब्लॉक स्कोप के समाप्त होने के तरीके की परवाह किए बिना निष्पादित होता है — return, break, throw, fatalError या सामान्य समाप्ति। Swift Language Guide (2025) के अनुसार, जब एक स्कोप में कई defer मौजूद होते हैं, तो वे घोषणा के विपरीत क्रम में निष्पादित होते हैं — अंतिम घोषित defer पहले चलता है (LIFO)। यह defer को संसाधनों की गारंटीशुदा सफाई के लिए अपरिहार्य बनाता है: फ़ाइल डिस्क्रिप्टर बंद करना, लॉक जारी करना, अस्थायी पॉइंटर्स मुक्त करना, जल्दी बाहर निकलने पर सफाई छूटने के जोखिम के बिना।
मुख्य बिंदु
defer Swift में एक नियंत्रण प्रवाह निर्माण है, जिसे Swift 2.0 (2015) में पेश किया गया, जो अपने ब्लॉक के निष्पादन को तब तक स्थगित करता है जब तक वर्तमान स्कोप समाप्त न हो जाए। मुख्य विशेषता: defer गारंटी देता है कि इसका बॉडी स्कोप के समाप्त होने के तरीके की परवाह किए बिना निष्पादित होगा — सफलतापूर्वक (return), त्रुटि के साथ (throw), समय से पहले (break, continue), या घातक रूप से (fatalError, precondition)।
वाक्यात्मक रूप से, defer defer { /* कोड */ } जैसा दिखता है और इसे स्कोप के अंदर कहीं भी रखा जा सकता है। Swift कंपाइलर गारंटी देता है कि defer के अंदर का कोड निष्पादित होगा भले ही defer की घोषणा और स्कोप के अंत के बीच कोई अपवाद या return हो। यह defer को फ़ंक्शन के अंत में रखे गए सामान्य कोड से मौलिक रूप से अलग करता है, जिसे जल्दी बाहर निकलने पर छोड़ा जा सकता है।
क्रिस लैटनर (Swift निर्माता, 2015) के एक लेख के अनुसार, defer अन्य भाषाओं में समान निर्माणों से प्रेरित था — Go में defer, Java/Python में finally, C++ में scope guard — लेकिन एक महत्वपूर्ण अंतर के साथ: Swift में, defer स्कोप के अंत में निष्पादित होता है, try-catch ब्लॉक के तुरंत बाद नहीं। यह एकाधिक निकास बिंदुओं वाले फ़ंक्शन में सफाई के लिए अधिक पूर्वानुमानित व्यवहार प्रदान करता है।
सममित संसाधन प्रबंधन के लिए defer का उपयोग करें: फ़ाइल खोलें → defer { close }, लॉक प्राप्त करें → defer { unlock }. यह पैटर्न गारंटी देता है कि किसी भी परिस्थिति में संसाधन मुक्त होना कभी नहीं छूटेगा।
जब एक ही स्कोप में कई defer घोषित किए जाते हैं, तो वे घोषणा के विपरीत क्रम में निष्पादित होते हैं (LIFO — Last In, First Out)। इसका मतलब है कि अंतिम घोषित defer पहले चलता है, और पहला घोषित अंतिम चलता है:
func exampleDeferOrder() {
defer { print("पहला defer") }
defer { print("दूसरा defer") }
defer { print("तीसरा defer") }
print("फ़ंक्शन बॉडी")
}
// आउटपुट:
// फ़ंक्शन बॉडी
// तीसरा defer
// दूसरा defer
// पहला defer
LIFO क्रम नेस्टेड संसाधनों के सही प्रबंधन के लिए महत्वपूर्ण है। यदि फ़ाइल A पहले खोली जाती है, फिर फ़ाइल B, तो उन्हें विपरीत क्रम में मुक्त किया जाना चाहिए: पहले B, फिर A। defer के साथ, यह स्वचालित रूप से होता है — प्रत्येक संसाधन खोलने के तुरंत बाद defer घोषित करें, और फ़ंक्शन में निकास बिंदुओं की संख्या की परवाह किए बिना सफाई क्रम सही होगा।
Swift by Sundell (2024) के अनुसार, यह विशेषता defer को नेस्टेड लॉक और लेन-देन के लिए आदर्श बनाती है: लॉक प्राप्त करें → defer { unlock } → अगला प्राप्त करें → defer { unlock }. LIFO गारंटी देता है कि लॉक प्राप्ति के विपरीत क्रम में जारी किए जाते हैं, डेडलॉक को रोकता है।
defer का मुख्य उपयोग मामला संसाधनों की गारंटीशुदा सफाई है। फ़ाइल सिस्टम के साथ काम करने पर विचार करें। FileHandle के माध्यम से फ़ाइल खोलने के लिए स्पष्ट रूप से बंद करने की आवश्यकता होती है — defer गारंटी देता है कि किसी भी परिदृश्य में close को कॉल किया जाएगा:
func readFile(path: String) throws -> String {
let handle = try FileHandle(forReadingFrom: URL(fileURLWithPath: path))
defer { try? handle.close() }
let data = try handle.readToEnd()
guard let data else { throw FileError.empty() }
return String(data: data, encoding: .utf8) ?? ""
// throw या return पर भी handle.close() कॉल किया जाएगा
}
एक अन्य विशिष्ट परिदृश्य लोडिंग फ़्लैग के साथ UI एनिमेशन है। लोड शुरू करने से पहले, फ़्लैग सेट करें isLoading = true, और defer फ़ंक्शन से बाहर निकलने पर इसे वापस false पर सेट करता है, अनुरोध की सफलता या विफलता की परवाह किए बिना। यह एक अनियंत्रित त्रुटि के कारण फ़्लैग के true रहने से रोकता है, जो इंटरफ़ेस को हमेशा के लिए ब्लॉक कर सकता है।
Bitbucket Engineering Blog (2024) के अनुसार, defer का उपयोग प्रोफ़ाइलिंग के लिए भी किया जाता है: फ़ंक्शन की शुरुआत में समय रिकॉर्ड करें, और defer में — अंतर की गणना करें और आउटपुट करें। यह त्रुटिपूर्ण सहित सभी निष्पादन पथों के लिए सटीक प्रदर्शन माप देता है।
defer throws फ़ंक्शन के साथ प्रभावी रूप से काम करता है। जब कोई फ़ंक्शन किसी भी चरण में त्रुटि फेंक सकता है, defer हर catch ब्लॉक या guard जल्दी निकास में कोड की नकल किए बिना सफाई सुनिश्चित करता है:
func processTransaction() throws {
let db = try openDatabase()
defer { closeDatabase(db) }
let user = try fetchUser(from: db)
defer { logAudit(user) }
let result = try performPayment(user)
sendNotification(result)
// closeDatabase(db) और logAudit(user) कॉल किए जाएंगे
// किसी भी throw या return पर
}
महत्वपूर्ण: defer नियंत्रण को catch ब्लॉक से बाहर स्थानांतरित करने से पहले निष्पादित होता है, लेकिन त्रुटि होने के बाद। यदि defer के अंदर कोई त्रुटि फेंकी जाती है, Swift defer के अंदर सीधे try का उपयोग करने की अनुमति नहीं देता है — आपको try? या try! की आवश्यकता है। Apple प्रलेखन के अनुसार, Swift त्रुटि को defer से बाहर निकलने की अनुमति नहीं देता है, क्योंकि इससे ब्लॉक के निष्पादन की गारंटी का उल्लंघन होगा।
संसाधन प्राप्त करने के तुरंत बाद defer रखें। यह निकटता के सिद्धांत का पालन करता है: पाठक प्राप्ति और मुक्ति को एक साथ देखता है, जो कोड विश्वसनीयता में सुधार करता है और कोड समीक्षा को सरल बनाता है।
defer उस स्कोप से बाहर निकलने पर निष्पादित होता है जिसमें इसे घोषित किया गया है। यदि defer do ब्लॉक के अंदर घोषित किया गया है, तो यह उस ब्लॉक से बाहर निकलने पर निष्पादित होता है, बाहरी फ़ंक्शन से नहीं। यदि for लूप के अंदर है — प्रत्येक पुनरावृत्ति पर:
func scopeExample() {
print("start")
do {
defer { print("do-ब्लॉक defer") }
print("inside do")
}
// "do-ब्लॉक defer" यहाँ प्रिंट होता है
print("after do")
}
// आउटपुट: start, inside do, do-ब्लॉक defer, after do
for i in 1...3 {
defer { print("end iteration \(i)") }
print("iteration \(i)")
}
// आउटपुट: iteration 1, end iteration 1, iteration 2, end iteration 2, ...
defer द्वारा कैप्चर किए गए चर स्कोप से बाहर निकलने के समय पढ़े जाते हैं, defer घोषणा के समय नहीं। यदि कोई चर defer की घोषणा और स्कोप के अंत के बीच बदलता है, defer नवीनतम मान देखेगा। यह क्लोज़र से एक महत्वपूर्ण अंतर है, जहां कैप्चर निर्माण के समय होता है। सावधान रहें: defer घोषित करने के बाद चर में परिवर्तन इसके निष्पादन को प्रभावित करेगा।
पहली गलती — LIFO के अलावा अन्य निष्पादन क्रम मान लेना। यदि सफाई क्रम मायने रखता है और defer गलत क्रम में घोषित किए गए हैं, तो संसाधन निर्भरता उल्लंघन के साथ मुक्त हो सकते हैं। समाधान: प्रत्येक संसाधन प्राप्त करने के तुरंत बाद defer घोषित करें। दूसरा संसाधन खोला गया → defer { close second } पहले के बंद होने से पहले।
दूसरी गलती — सफाई से असंबंधित तर्क के लिए defer का उपयोग करना। defer गारंटीशुदा सफाई के लिए है, मुख्य प्रवाह नियंत्रण के लिए नहीं। यदि defer के अंदर का कोड वापसी मान को प्रभावित करता है, तो यह लगभग हमेशा एक गलती है। defer किसी फ़ंक्शन का वापसी मान नहीं बदल सकता (Java finally के विपरीत, जहां finally में return मूल return को ओवरराइट करता है)।
तीसरी गलती — defer से त्रुटि फेंकना। Swift defer के अंदर try को प्रतिबंधित करता है यदि त्रुटि बाहर फैल सकती है। उन संचालनों के लिए try? या try! का उपयोग करें जो त्रुटि फेंक सकते हैं, या उन्हें throws के बिना एक अलग फ़ंक्शन में लपेटें। O’Reilly “Swift in Depth” (2025) के अनुसार, एक अच्छी प्रथा सफाई फ़ंक्शन को non-throwing बनाना या defer के अंदर त्रुटियों को संभालना है।
अक्सर पूछे जाने वाले प्रश्न
defer एक Swift निर्माण है जो एक ब्लॉक के निष्पादन को तब तक स्थगित करता है जब तक वर्तमान स्कोप समाप्त न हो जाए। ब्लॉक हमेशा निष्पादित होता है — return, throw, break या सामान्य समाप्ति पर। इसका उपयोग संसाधनों की गारंटीशुदा सफाई के लिए किया जाता है: फ़ाइलें बंद करना, लॉक जारी करना।
घोषणा के विपरीत क्रम में (LIFO) — अंतिम घोषित defer पहले चलता है। यह नेस्टेड संसाधनों की सही सफाई सुनिश्चित करता है: यदि संसाधन B, A के बाद खोला जाता है, तो इसे A से पहले बंद किया जाएगा, पहले से मुक्त संसाधनों पर निर्भरता को रोकता है।
सीधे तौर पर नहीं — Swift defer से त्रुटि प्रसार को रोकता है। उन संचालनों के लिए try? या try! का उपयोग करें जो त्रुटि फेंक सकते हैं। सबसे अच्छी प्रथा सफाई फ़ंक्शन को non-throwing बनाना या defer के अंदर त्रुटियों को बाहर प्रसारित किए बिना संभालना है।
defer एक स्कोप से बंधा होता है और किसी भी निकास पर निष्पादित होता है, जिसमें return, throw और break शामिल हैं। finally (अन्य भाषाओं में) try-catch से बंधा होता है और केवल try मौजूद होने पर निष्पादित होता है। Swift में finally नहीं है — defer इस परिदृश्य को पूरी तरह से कवर करता है और किसी भी स्कोप के लिए काम करता है, न कि केवल त्रुटि प्रबंधन के लिए।
हाँ, defer स्कोप से बाहर निकलने के समय चर पढ़ता है, घोषणा के समय नहीं। यदि defer घोषित होने के बाद कोई चर बदलता है, defer ब्लॉक नवीनतम मान देखेगा। यह सामान्य क्लोज़र से भिन्न है, जहां कैप्चर निर्माण के समय तय हो जाता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें