परिचय: "प्रतीक्षा करना" उतना आसान क्यों नहीं है जितना लगता है
\n\nकल्पना करें: आप Swift 3 में iOS के लिए एक ऐप लिख रहे हैं। एक एनिमेशन दिखाना है, और कुछ सेकंड बाद उसे छिपाना है। या सर्वर पर अनुरोध भेजना है, लेकिन तुरंत नहीं, बल्कि विलंब के साथ। लगता है, इससे आसान क्या हो सकता है? बस sleep(2) लिखें और हो गया। लेकिन अगर आप ऐसा करते हैं, तो आपका ऐप बर्फ के टुकड़े में बदल जाएगा: इंटरफ़ेस फ्रीज हो जाएगा, उपयोगकर्ता स्क्रीन पर टैप करना शुरू कर देगा, और अंत में - नकारात्मक समीक्षा और रेटिंग में गिरावट।
"How to program a delay in Swift 3" प्रश्न ने Stack Overflow पर हज़ारों व्यूज़ प्राप्त किए हैं। और यह कोई संयोग नहीं है: शुरुआती लोग बार-बार एक ही गलती करते हैं। इस लेख में हम केवल तैयार नुस्खा नहीं देंगे। हम विलंब तंत्र के अंदर झाँकेंगे, समझेंगे कि DispatchQueue.main.asyncAfter कैसे काम करता है, और जानेंगे कि sleep बुराई क्यों है। और मैं आपको एक ऐसी ट्रिक भी दिखाऊंगा जो डीबगिंग के घंटे बचाएगी।
Swift में sleep() एक एंटी-पैटर्न क्यों है
\n\nआइए सबसे लोकप्रिय गलतफहमी को तुरंत दूर करें। कई लोग जो अन्य भाषाओं (जैसे Python से time.sleep()) से आते हैं, ऐसा करने की कोशिश करते हैं:
sleep(2) // थ्रेड को 2 सेकंड के लिए ब्लॉक करें\nprint("2 सेकंड बीत गए")\n\nयह कोड वर्तमान थ्रेड को ब्लॉक करता है। यदि आप इसे मुख्य थ्रेड (main thread) पर कॉल करते हैं - बस, ऐप 2 सेकंड के लिए "सो जाता है"। उपयोगकर्ता इंटरफ़ेस अपडेट नहीं होता, बटन दबाए नहीं जाते, एनिमेशन काम नहीं करते। यदि मुख्य थ्रेड बहुत देर (आमतौर पर 10 सेकंड से अधिक) तक ब्लॉक रहता है, तो iOS आपके ऐप को मार देगा।
\n\nइसके अलावा, sleep() RunLoop की स्थिति को ध्यान में नहीं रखता। यह एक कच्चा सिस्टम कॉल है जो सिस्टम को सामान्य रूप से इवेंट प्रोसेस करने नहीं देता। Swift 3 (और उसके बाद) में सही तरीका Grand Central Dispatch (GCD) का उपयोग करना है।
DispatchQueue.main.asyncAfter: विलंब करने का सही तरीका
\n\nSwift 3 में कोड के निष्पादन में देरी करने का सबसे सामान्य और अनुशंसित तरीका GCD का asyncAfter मेथड है। यह इस तरह दिखता है:
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {\n print("2 सेकंड बीत गए (नॉन-ब्लॉकिंग मोड)")\n}\n\nयहाँ हम सिस्टम से कहते हैं: "वर्तमान समय से 2 सेकंड बाद, कोड के इस ब्लॉक को मुख्य थ्रेड पर निष्पादित करो"। मुख्य थ्रेड इस दौरान स्वतंत्र रहता है - एनिमेशन काम करते हैं, बटन दबाए जाते हैं, उपयोगकर्ता खुश रहता है।
\n\nलेकिन आइए गहराई से समझें। deadline क्या है? .now() + 2.0 क्यों, न कि केवल 2.0? और "अंदर" क्या होता है?
asyncAfter की संरचना: deadline, DispatchTime और DispatchQoS
\n\nasyncAfter DispatchTime प्रकार का deadline पैरामीटर लेता है। यह केवल मिलीसेकंड की संख्या नहीं है, बल्कि सिस्टम क्लॉक से जुड़ा एक पूर्ण समय बिंदु है। जब आप .now() + 2.0 लिखते हैं, GCD गणना करता है: "वर्तमान समय + 2 सेकंड" और कार्य को इस टैग के साथ कतार में रखता है।
अंदर, GCD mach_absolute_time() का उपयोग करता है - एक हार्डवेयर टाइमर जो सिस्टम समय में बदलाव पर निर्भर नहीं करता। यानी अगर उपयोगकर्ता घड़ी पीछे करता है, तो आपका विलंब टूटेगा नहीं (Timer के विपरीत, जो अप्रत्याशित व्यवहार कर सकता है)।
एक महत्वपूर्ण बारीकी: deadline निष्पादन के लिए न्यूनतम समय है। GCD गारंटी नहीं देता कि कोड ठीक 2 सेकंड में निष्पादित होगा। यदि सिस्टम व्यस्त है (जैसे, जटिल डेटा प्रोसेसिंग चल रही है), तो निष्पादन में देरी हो सकती है। अधिकांश UI कार्यों के लिए यह महत्वपूर्ण नहीं है, लेकिन उच्च-सटीकता वाले टाइमर (जैसे गेम में) के लिए CADisplayLink का उपयोग करना बेहतर है।
एक और पैरामीटर है - qos (Quality of Service)। आप कार्य की प्राथमिकता निर्दिष्ट कर सकते हैं:
DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + 1.0) {\n // उच्च प्राथमिकता वाला कार्य\n}\n\n
ब्लॉग
पुस्तक अनुशंसाएँ
यह भी पढ़ें
C++ में डोमेन-ड्रिवन डिज़ाइन: जटिल परियोजनाओं के लिए आर्किटेक्चर
JavaScript में Generics: क्यों आवश्यक हैं और व्यवहार में कैसे उपयोग करें
कोटलिन एप्लिकेशन सुरक्षा: शुरुआती लोगों के लिए शीर्ष 10 कमजोरियाँ
Swift कोड प्रोफाइलिंग: शुरुआती लोगों के लिए बाधाएं खोजना
PHP विकास के लिए सर्वश्रेष्ठ IDE और उपकरण: उन्नत स्तर