defer — यह क्या है, सिंटैक्स और निष्पादन क्रम

लेखक: IT Sectr प्रकाशित: 2026-06-20 पढ़ने का समय: 8 मिनट

defer Swift में एक नियंत्रण प्रवाह निर्माण है जो वर्तमान स्कोप से बाहर निकलने पर कोड के एक ब्लॉक के निष्पादन को शेड्यूल करता है। defer ब्लॉक स्कोप के समाप्त होने के तरीके की परवाह किए बिना निष्पादित होता है — return, break, throw, fatalError या सामान्य समाप्ति। Swift Language Guide (2025) के अनुसार, जब एक स्कोप में कई defer मौजूद होते हैं, तो वे घोषणा के विपरीत क्रम में निष्पादित होते हैं — अंतिम घोषित defer पहले चलता है (LIFO)। यह defer को संसाधनों की गारंटीशुदा सफाई के लिए अपरिहार्य बनाता है: फ़ाइल डिस्क्रिप्टर बंद करना, लॉक जारी करना, अस्थायी पॉइंटर्स मुक्त करना, जल्दी बाहर निकलने पर सफाई छूटने के जोखिम के बिना।

मुख्य बिंदु

  • defer — कोड का एक ब्लॉक जो स्कोप से बाहर निकलने पर निष्पादित होता है, बाहर निकलने के कारण (return, throw, break) की परवाह किए बिना
  • LIFO क्रम: कई defer नीचे से ऊपर निष्पादित होते हैं — अंतिम घोषित पहले चलता है
  • संसाधन सफाई — मुख्य उपयोग: फ़ाइलें बंद करना, लॉक जारी करना, एनिमेशन पूरा करना
  • चर मूल्यांकन: defer बाहर निकलने के समय चर को देखता है, घोषणा के समय नहीं
  • प्रतिस्थापित नहीं करता त्रुटि प्रबंधन के लिए do-catch — defer सफाई संभालता है, प्रवाह नियंत्रण नहीं

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 का निष्पादन क्रम

जब एक ही स्कोप में कई defer घोषित किए जाते हैं, तो वे घोषणा के विपरीत क्रम में निष्पादित होते हैं (LIFO — Last In, First Out)। इसका मतलब है कि अंतिम घोषित defer पहले चलता है, और पहला घोषित अंतिम चलता है:

swift
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

defer का मुख्य उपयोग मामला संसाधनों की गारंटीशुदा सफाई है। फ़ाइल सिस्टम के साथ काम करने पर विचार करें। FileHandle के माध्यम से फ़ाइल खोलने के लिए स्पष्ट रूप से बंद करने की आवश्यकता होती है — defer गारंटी देता है कि किसी भी परिदृश्य में close को कॉल किया जाएगा:

swift
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 और त्रुटि प्रबंधन

defer throws फ़ंक्शन के साथ प्रभावी रूप से काम करता है। जब कोई फ़ंक्शन किसी भी चरण में त्रुटि फेंक सकता है, defer हर catch ब्लॉक या guard जल्दी निकास में कोड की नकल किए बिना सफाई सुनिश्चित करता है:

swift
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 लूप के अंदर है — प्रत्येक पुनरावृत्ति पर:

swift
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 घोषित करने के बाद चर में परिवर्तन इसके निष्पादन को प्रभावित करेगा।

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 के अंदर त्रुटियों को संभालना है।

अक्सर पूछे जाने वाले प्रश्न

Swift में defer क्या है?

defer एक Swift निर्माण है जो एक ब्लॉक के निष्पादन को तब तक स्थगित करता है जब तक वर्तमान स्कोप समाप्त न हो जाए। ब्लॉक हमेशा निष्पादित होता है — return, throw, break या सामान्य समाप्ति पर। इसका उपयोग संसाधनों की गारंटीशुदा सफाई के लिए किया जाता है: फ़ाइलें बंद करना, लॉक जारी करना।

एकाधिक defer किस क्रम में निष्पादित होते हैं?

घोषणा के विपरीत क्रम में (LIFO) — अंतिम घोषित defer पहले चलता है। यह नेस्टेड संसाधनों की सही सफाई सुनिश्चित करता है: यदि संसाधन B, A के बाद खोला जाता है, तो इसे A से पहले बंद किया जाएगा, पहले से मुक्त संसाधनों पर निर्भरता को रोकता है।

क्या defer से त्रुटि फेंकी जा सकती है?

सीधे तौर पर नहीं — Swift defer से त्रुटि प्रसार को रोकता है। उन संचालनों के लिए try? या try! का उपयोग करें जो त्रुटि फेंक सकते हैं। सबसे अच्छी प्रथा सफाई फ़ंक्शन को non-throwing बनाना या defer के अंदर त्रुटियों को बाहर प्रसारित किए बिना संभालना है।

defer और do-catch-finally में क्या अंतर है?

defer एक स्कोप से बंधा होता है और किसी भी निकास पर निष्पादित होता है, जिसमें return, throw और break शामिल हैं। finally (अन्य भाषाओं में) try-catch से बंधा होता है और केवल try मौजूद होने पर निष्पादित होता है। Swift में finally नहीं है — defer इस परिदृश्य को पूरी तरह से कवर करता है और किसी भी स्कोप के लिए काम करता है, न कि केवल त्रुटि प्रबंधन के लिए।

क्या defer अपनी घोषणा के बाद चर में परिवर्तन देखता है?

हाँ, defer स्कोप से बाहर निकलने के समय चर पढ़ता है, घोषणा के समय नहीं। यदि defer घोषित होने के बाद कोई चर बदलता है, defer ब्लॉक नवीनतम मान देखेगा। यह सामान्य क्लोज़र से भिन्न है, जहां कैप्चर निर्माण के समय तय हो जाता है।

सारांश

  • defer — एक अंतिमकरण ब्लॉक जो कारण (return, throw, break, सामान्य समाप्ति) की परवाह किए बिना स्कोप से बाहर निकलने पर निष्पादित होता है
  • LIFO क्रम — कई defer नीचे से ऊपर निष्पादित होते हैं, अंतिम घोषित पहले चलता है
  • संसाधन सफाई — मुख्य उपयोग: फ़ाइलें बंद करना, लॉक जारी करना, पॉइंटर्स मुक्त करना, एनिमेशन रोकना
  • throws के साथ संगतता: defer त्रुटि के बाद लेकिन catch ब्लॉक से बाहर निकलने से पहले निष्पादित होता है; defer से त्रुटियाँ प्रसारित नहीं होतीं
  • स्कोप: defer उस स्कोप से बाहर निकलने पर निष्पादित होता है जहाँ इसे घोषित किया गया था — do ब्लॉक, लूप, फ़ंक्शन
  • चर कैप्चर: defer निकास समय पर मान पढ़ता है, घोषणा समय पर नहीं — परिवर्तनों से सावधान रहें
  • सर्वोत्तम प्रथा: संसाधन प्राप्त करने के तुरंत बाद defer घोषित करें, व्यावसायिक तर्क के लिए defer का उपयोग न करें, सफाई फ़ंक्शन को non-throwing बनाएँ

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें