Swift में त्रुटि प्रबंधन: try/catch और अन्य
आधुनिक iOS और macOS डेवलपमेंट में, एप्लिकेशन की विश्वसनीयता गुणवत्ता के प्रमुख संकेतकों में से एक है। Swift में उचित त्रुटि प्रबंधन न केवल अप्रत्याशित क्रैश से बचाता है, बल्कि कोड को अधिक पठनीय और पूर्वानुमानित भी बनाता है। इस लेख में, हम न केवल क्लासिक try/catch तंत्र को समझेंगे, बल्कि वैकल्पिक दृष्टिकोणों को भी देखेंगे, जिनमें Result प्रकार, defer ऑपरेटर और उन्नत पैटर्न शामिल हैं।
मूल बातें: Error प्रोटोकॉल और throws कीवर्ड
Swift में, त्रुटियाँ उन प्रकारों द्वारा दर्शायी जाती हैं जो Error प्रोटोकॉल का अनुपालन करते हैं। इसके लिए अक्सर एनुम (enum) का उपयोग किया जाता है। किसी फ़ंक्शन को त्रुटि फेंकने में सक्षम बनाने के लिए, इसकी घोषणा में throws कीवर्ड का उपयोग किया जाता है।
enum NetworkError: Error { case noInternet case serverError(code: Int) case timeout}
func fetchData(from url: String) throws -> Data { guard url.hasPrefix("https") else { throw NetworkError.serverError(code: 400) } // ... डाउनलोड का अनुकरण return Data()}ध्यान दें: यदि किसी फ़ंक्शन को throws से चिह्नित किया गया है, तो कॉल करने वाले कोड को try, try? या try! का उपयोग करके संभावित त्रुटि को संभालना अनिवार्य है।
do-catch संरचना: क्लासिक दृष्टिकोण
सबसे सामान्य प्रबंधन विधि do-catch ब्लॉक है। आप संभावित रूप से खतरनाक कोड को do के अंदर रखते हैं, और catch में बताते हैं कि प्रत्येक विशिष्ट त्रुटि के साथ क्या करना है।
do { let data = try fetchData(from: "http://example.com") print("डेटा प्राप्त हुआ: \\(data)")} catch NetworkError.noInternet { print("इंटरनेट से कनेक्शन नहीं है")} catch NetworkError.serverError(let code) { print("कोड के साथ सर्वर त्रुटि: \\(code)")} catch { print("अज्ञात त्रुटि: \\(error.localizedDescription)")}महत्वपूर्ण: अंतिम catch ब्लॉक बिना किसी पैटर्न के सभी शेष त्रुटियों को पकड़ लेता है। अप्रत्याशित अपवादों को न चूकने के लिए यह एक अच्छा अभ्यास है।
try? और try!: त्वरित विकल्प
यदि आपको त्रुटि के प्रकार की परवाह नहीं है, और केवल यह जानना है कि फ़ंक्शन सफलतापूर्वक निष्पादित हुआ या नहीं, तो try? का उपयोग करें। त्रुटि की स्थिति में, परिणाम nil होगा।
if let data = try? fetchData(from: "https://valid.com") { print("सफलता: \\(data)")} else { print("लोड करने में त्रुटि")}try! ऑपरेटर एक "टाइम बम" है। यह त्रुटि प्रबंधन को दबा देता है और यदि त्रुटि होती है तो एप्लिकेशन क्रैश हो जाता है। इसका उपयोग केवल उन मामलों में करें जहाँ आप 100% आश्वस्त हों कि कोई त्रुटि नहीं होगी (उदाहरण के लिए, बिल्ट-इन रिसोर्स लोड करते समय)।
let data = try! fetchData(from: "https://trusted-source.com")// यदि त्रुटि है — एप्लिकेशन क्रैश हो जाएगाResult प्रकार: कार्यात्मक दृष्टिकोण
Swift 5 से शुरू होकर, स्टैंडर्ड लाइब्रेरी में Result<Success, Failure> प्रकार जोड़ा गया। यह एक क्लोजर है जिसमें या तो सफल मान या त्रुटि हो सकती है। यह दृष्टिकोण विशेष रूप से एसिंक्रोनस कोड और कॉलबैक फ़ंक्शन (completion handlers) में सुविधाजनक है।
func fetchDataResult(from url: String) -> Result<Data, NetworkError> { guard url.hasPrefix("https") else { return .failure(.serverError(code: 400)) } return .success(Data())}
// उपयोगlet result = fetchDataResult(from: "http://bad.com")switch result {case .success(let data): print("डेटा: \\(data)")case .failure(let error): print("त्रुटि: \\(error)")}Result का लाभ यह है कि आप त्रुटि को संभालना नहीं भूलते, क्योंकि कंपाइलर आपको मजबूर करता है