जब किसी फ़ंक्शन throws
को स्विफ्ट के साथ घोषित किया जाता है, तो आपको फ़ंक्शन कॉल साइट को एनोटेट करना चाहिए try
या उसके साथ try!
। उदाहरण के लिए, एक फेंकने का कार्य दिया गया:
func willOnlyThrowIfTrue(value: Bool) throws {
if value { throw someError }
}
इस समारोह को इस तरह कहा जा सकता है:
func foo(value: Bool) throws {
try willOnlyThrowIfTrue(value)
}
यहां हम कॉल को एनोटेट करते हैं try
, जो पाठक को कहता है कि यह फ़ंक्शन अपवाद फेंक सकता है, और कोड के किसी भी निम्नलिखित लाइनों को निष्पादित नहीं किया जा सकता है। हमें इस फ़ंक्शन को भी एनोटेट करना होगा throws
, क्योंकि यह फ़ंक्शन एक अपवाद फेंक सकता है (यानी, जब willOnlyThrowIfTrue()
फेंकता है, तो foo
स्वचालित रूप से अपवाद को ऊपर की ओर फिर से फेंक देगा।
यदि आप एक फ़ंक्शन को कॉल करना चाहते हैं जिसे संभवतः फेंकने के रूप में घोषित किया गया है, लेकिन जिसे आप जानते हैं वह आपके मामले में नहीं फेंकेंगे क्योंकि आप इसे सही इनपुट दे रहे हैं, तो आप उपयोग कर सकते हैं try!
।
func bar() {
try! willOnlyThrowIfTrue(false)
}
इस तरह, जब आप गारंटी देते हैं कि कोड नहीं फेंकेगा, तो आपको अपवाद प्रचार को अक्षम करने के लिए अतिरिक्त बॉयलरप्लेट कोड में नहीं डालना होगा।
try!
रनटाइम पर लागू किया जाता है: यदि आप उपयोग करते हैं try!
और फ़ंक्शन समाप्त हो जाता है, तो रनटाइम त्रुटि के साथ आपके प्रोग्राम का निष्पादन समाप्त हो जाएगा।
अधिकांश अपवाद हैंडलिंग कोड को ऊपर की तरह दिखना चाहिए: या तो आप अपवादों को ऊपर की ओर प्रचारित करते हैं, जब वे होते हैं, या आप ऐसी स्थिति सेट करते हैं, अन्यथा संभव अपवादों को खारिज कर दिया जाता है। आपके कोड में मौजूद अन्य संसाधनों की सफाई वस्तु विनाश (यानी deinit()
), या कभी-कभी defer
एड कोड के माध्यम से होनी चाहिए ।
func baz(value: Bool) throws {
var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
var data = NSData(contentsOfFile:filePath)
try willOnlyThrowIfTrue(value)
// data and filePath automatically cleaned up, even when an exception occurs.
}
यदि किसी भी कारण से आपके पास क्लीन अप कोड है जिसे चलाने की आवश्यकता है लेकिन deinit()
फ़ंक्शन में नहीं है , तो आप उपयोग कर सकते हैं defer
।
func qux(value: Bool) throws {
defer {
print("this code runs when the function exits, even when it exits by an exception")
}
try willOnlyThrowIfTrue(value)
}
अधिकांश कोड जो अपवादों से संबंधित हैं, उन्हें कॉल करने वालों के लिए ऊपर की ओर प्रचारित किया जाता है, रास्ते से सफाई कर रहा है deinit()
या defer
। ऐसा इसलिए है क्योंकि अधिकांश कोड को पता नहीं है कि त्रुटियों का क्या करना है; यह पता है कि क्या गलत हुआ, लेकिन इसमें इस बारे में पर्याप्त जानकारी नहीं है कि कुछ उच्च स्तरीय कोड क्या करने की कोशिश कर रहे हैं ताकि यह पता चल सके कि त्रुटि के बारे में क्या करना है। यह नहीं पता कि उपयोगकर्ता के लिए एक संवाद प्रस्तुत करना उचित है, या यदि उसे पुनः प्रयास करना चाहिए, या यदि कुछ और उपयुक्त है।
उच्च स्तरीय कोड, हालांकि, किसी भी त्रुटि की स्थिति में वास्तव में क्या करना चाहिए, यह जानना चाहिए। इसलिए अपवाद विशिष्ट त्रुटियों को बुलबुले बनाने की अनुमति देते हैं जहां से वे शुरू में वहां होते हैं जहां उन्हें संभाला जा सकता है।
अपवादों को संभालना catch
बयानों के माध्यम से किया जाता है ।
func quux(value: Bool) {
do {
try willOnlyThrowIfTrue(value)
} catch {
// handle error
}
}
आपके पास कई कैच स्टेटमेंट हो सकते हैं, प्रत्येक एक अलग तरह के अपवाद को पकड़ सकता है।
do {
try someFunctionThatThowsDifferentExceptions()
} catch MyErrorType.errorA {
// handle errorA
} catch MyErrorType.errorB {
// handle errorB
} catch {
// handle other errors
}
अपवादों के साथ सर्वोत्तम प्रथाओं के बारे में अधिक जानकारी के लिए, http://exceptionafecode.com/ देखें । यह विशेष रूप से C ++ पर लक्षित है, लेकिन स्विफ्ट अपवाद मॉडल की जांच करने के बाद, मेरा मानना है कि मूल स्विफ्ट पर भी लागू होता है।
स्विफ्ट सिंटैक्स और एरर हैंडलिंग मॉडल के विवरण के लिए, द स्विफ्ट प्रोग्रामिंग लैंग्वेज (स्विफ्ट 2 प्रीलेयरेज़) पुस्तक देखें ।