Swift में त्रुटि प्रबंधन: try/catch और भी बहुत कुछ (उन्नत स्तर)
\n\nत्रुटि प्रबंधन Swift में डेवलपमेंट के प्रमुख विषयों में से एक है। यदि आप पहले से ही बुनियादी do-catch और try? से परिचित हैं, तो अब एक नए स्तर पर जाने का समय आ गया है। इस लेख में हम उन्नत तकनीकों पर चर्चा करेंगे: Error प्रोटोकॉल के साथ काम करना, Result प्रकार, rethrows कीवर्ड, और वास्तविक iOS/macOS प्रोजेक्ट्स में त्रुटियों के पदानुक्रम को सही ढंग से डिज़ाइन करना।
Error प्रोटोकॉल और कस्टम त्रुटियों में गहराई से उतरना
\n\nSwift में किसी भी त्रुटि को Error प्रोटोकॉल का पालन करना चाहिए। हालांकि, कोड को अधिक पठनीय और रखरखाव योग्य बनाने के लिए, नेस्टेड केस और एसोसिएटेड वैल्यू के साथ अपने स्वयं के एनम (enum) बनाना उचित है।
enum NetworkError: Error {\n case invalidURL\n case noData\n case decodingFailed(description: String)\n case serverError(statusCode: Int)\n case timeout(seconds: Double)\n}\n\n// उपयोग का उदाहरण\nfunc fetchUser(id: Int) throws -> User {\n guard id > 0 else {\n throw NetworkError.invalidURL\n }\n // ... अनुरोध का तर्क\n if someCondition {\n throw NetworkError.serverError(statusCode: 500)\n }\n return User()\n}\n\nयह दृष्टिकोण अतिरिक्त संदर्भ प्रदान करने की अनुमति देता है: त्रुटि कोड, विवरण या प्रतीक्षा समय। यह लॉगिंग और डीबगिंग के दौरान विशेष रूप से उपयोगी है।
\n\nResult: एसिंक्रोनस कोड के लिए do-catch का विकल्प
\n\nResult<Success, Failure> प्रकार एक शक्तिशाली उपकरण है जो कार्यात्मक प्रोग्रामिंग से आया है। यह callback-आधारित API, नेटवर्क अनुरोधों और एसिंक्रोनस संचालन के लिए आदर्श है।
enum DataError: Error {\n case corrupted\n case notFound\n}\n\nfunc loadImage(from url: URL, completion: @escaping (Result<UIImage, DataError>) -> Void) {\n DispatchQueue.global().async {\n // लोडिंग का अनुकरण\n if arc4random_uniform(2) == 0 {\n completion(.success(UIImage()))\n } else {\n completion(.failure(.notFound))\n }\n }\n}\n\n// उपयोग\nloadImage(from: someURL) { result in\n switch result {\n case .success(let image):\n print("इमेज लोड हुई: \\(image)")\n case .failure(let error):\n print("त्रुटि: \\(error.localizedDescription)")\n }\n}\n\nResult कोड को अधिक अनुमानित बनाता है और nil के साथ वैकल्पिक मानों को संभालने की आवश्यकता को समाप्त करता है। इसके अलावा, आप ट्रांसफॉर्मेशन की श्रृंखला के लिए .map और .flatMap का उपयोग कर सकते हैं।
Rethrows: जब फ़ंक्शन त्रुटियों को "पास" करता है
\n\nrethrows कीवर्ड Swift की सबसे कम सराही गई क्षमताओं में से एक है। यह एक ऐसा फ़ंक्शन लिखने की अनुमति देता है जो स्वयं त्रुटियाँ नहीं फेंकता, लेकिन यदि पास किया गया क्लोज़र (closure) throws है तो उन्हें "आगे बढ़ा" देता है।
func performOperation<T>(on array: [T], operation: (T) throws -> Bool) rethrows -> [T] {\n var result: [T] = []\n for element in array {\n if try operation(element) {\n result.append(element)\n }\n }\n return result\n}\n\n// बिना त्रुटि के (try की आवश्यकता नहीं)\nlet numbers = [1, 2, 3, 4, 5]\nlet evenNumbers = performOperation(on: numbers) { $0.isMultiple(of: 2) }\nprint(evenNumbers) // [2, 4]\n\n// त्रुटि के साथ (try की आवश्यकता)\nenum ValidationError: Error { case negative }\nlet filtered = try performOperation(on: numbers) { value in\n guard value > 0 else { throw ValidationError.negative }\n return value % 2 == 0\n}\n\nrethrows API को लचीला बनाता है: उपयोगकर्ता एक सामान्य क्लोज़र (बिना try के) या throws वाला क्लोज़र (तब try की आवश्यकता होगी) पास कर सकता है। इसका उपयोग Swift की मानक लाइब्रेरी में अक्सर किया जाता है — उदाहरण के लिए, map, filter और for में।