उद्देश्य-सी: अभिकथन बनाम अपवाद बनाम त्रुटि


79

कोको में, मुझे एनएसएसरटेर, एनएसईएक्ससेप्शन, एनएसईआरओआरआर का उपयोग कब करना चाहिए?

यहाँ मैं सोच रहा हूँ:

NSAssert - प्रोग्रामर के लिए उपयोग किए जाने वाले किसी भी क्लाइंट प्रोग्राम को बनाते समय डबल चेक नियमों, सम्मेलनों, मान्यताओं, या पूर्व-स्थितियों और पोस्ट-शर्तों के लिए स्वयं के लाभ के लिए?

NSException - पुस्तकालय का उपयोग करने वाले अन्य प्रोग्रामरों के लाभ के लिए एक तृतीय-पक्ष लाइब्रेरी बनाते समय, ताकि उन्हें तुरंत पता चल जाए कि इनपुट अमान्य है या नहीं?

NSError - जब एक फ़ाइल, डेटाबेस या वेब सेवा की तरह डेटा प्राप्त करने के लिए किसी बाहरी प्रणाली के साथ इंटरफेस किया जाता है जो मुझे परिणाम देने की गारंटी नहीं है?

जवाबों:


103

असफल होने पर एक NSAssert अपवाद फेंक देगा। तो NSAssert लिखने के लिए और आपके कोड में आपके द्वारा की गई किसी भी मान्यताओं की जांच करने के लिए छोटा और आसान तरीका है। यह (मेरी राय में) अपवादों का विकल्प नहीं है, सिर्फ एक शॉर्टकट है। यदि एक जोरदार विफल रहता है तो आपके कोड में कुछ गलत हो गया है और कार्यक्रम जारी नहीं होना चाहिए।

ध्यान देने वाली बात यह है कि NSAssert एक रिलीज बिल्ड में आपके कोड में संकलित नहीं किया जाएगा, इसलिए यह आमतौर पर विकास के लिए स्वच्छता की जाँच के लिए उपयोग किया जाता है। मैं वास्तव में एक कस्टम मुखर मैक्रो का उपयोग करता हूं जो हमेशा सक्रिय रहता है।

जिस समय आप @throwअपने स्वयं के NSException होंगे , जब आप निश्चित रूप से इसे रिलीज़ बिल्ड में चाहते हैं, और सार्वजनिक पुस्तकालयों / इंटरफ़ेस जैसी चीजों में जब कुछ तर्क अमान्य हैं या आपको गलत तरीके से बुलाया गया है। ध्यान दें कि यह वास्तव में @catchएक अपवाद के लिए मानक अभ्यास नहीं है और अपना एप्लिकेशन चलाना जारी रखें। यदि आप एप्पल के कुछ मानक पुस्तकालयों (उदाहरण के लिए कोर डेटा) के साथ यह कोशिश करते हैं तो बुरी चीजें हो सकती हैं। एक मुखर के समान, अगर एक अपवाद को फेंक दिया जाता है, तो एप्लिकेशन को आमतौर पर काफी जल्दी समाप्त करना चाहिए क्योंकि इसका मतलब है कि कहीं न कहीं एक प्रोग्रामिंग त्रुटि है।

NSErrors को आपके पुस्तकालयों / इंटरफेस में उन त्रुटियों के लिए उपयोग किया जाना चाहिए जो प्रोग्रामिंग त्रुटियां नहीं हैं, और जिनसे पुनर्प्राप्त किया जा सकता है। आप कॉल करने वाले को सूचना / त्रुटि कोड प्रदान कर सकते हैं और वे त्रुटि को सफाई से संभाल सकते हैं, यदि उपयुक्त हो तो उपयोगकर्ता को सचेत कर सकते हैं और निष्पादन जारी रख सकते हैं। यह आमतौर पर फाइल-नहीं-पाया त्रुटि या कुछ अन्य गैर-घातक त्रुटि जैसी चीजों के लिए होगा।


15
इसे और अधिक मजबूती से रखने के लिए, पुनर्प्राप्ति त्रुटि को इंगित करने के लिए एक NSException का उपयोग नहीं किया जाना चाहिए।
bbum

28
दूसरे शब्दों में: ओब्ज-सी का NSException == जावा का त्रुटि वर्ग, और ओब्ज-सी का एनएसईआरओआर == जावा का अपवाद वर्ग। शब्दों में स्थिरता के लिए हुर्रे!
Tustin2121

2
वास्तव में, यदि आप अपने पहले से तैयार उपसर्ग फाइलों में NS_BLOCK_ASSERTIONS नहीं जोड़ते हैं तो NSAssert आपके कोड में संकलित किया जाएगा। नीचे दिए गए उत्तर को पढ़ें (अभी केवल 50 प्राप्त करने के लिए :) :)
likid1412

3

कोको में सम्मेलन एक अपवाद एक प्रोग्रामर त्रुटि को इंगित करता है। एक अपवाद को फेंकने के बाद फ्रेमवर्क कोड सहित बहुत सारे कोड को ठीक से काम करने के लिए डिज़ाइन नहीं किया गया है।

किसी भी प्रकार की त्रुटि जो पुनर्प्राप्त करने योग्य होनी चाहिए, एक द्वारा दर्शाई गई है NSErrorNSErrorउपयोगकर्ता के लिए प्रस्तुत करने के लिए एक प्रणाली भी है । जैसा कि आप कहते हैं, यह ज्यादातर परिवर्तनीय बाहरी संसाधनों के लिए उपयोगी है।

वैचारिक रूप से, एक कथन एक कथन है जो एक दिया हुआ विधेय हमेशा सत्य का मूल्यांकन करता है; यदि ऐसा नहीं होता है, तो कार्यक्रम टूट गया है। हालांकि इसके व्यवहार को संशोधित किया जा सकता है, NSAssertपरिवार डिफ़ॉल्ट रूप से NSInternalInconsistencyExceptionएस फेंकने का एक सुविधाजनक तरीका है (रिलीज बिल्ड में उन्हें बंद करने के विकल्प के साथ)।


2

संपादित करें: Xcode 4.2 में, रिलीज़ बिल्ड के लिए डिफ़ॉल्ट रूप से दावे बंद किए गए हैं,

अब NSAssert एक रिलीज़ बिल्ड में आपके कोड में संकलित नहीं किया जाएगा , लेकिन आप इसे बिल्ड सेटिंग्स में बदल सकते हैं


@ माइक वेलर, आपके उत्तर में एक गलत हैं।

ध्यान देने वाली बात यह है कि NSAssert एक रिलीज बिल्ड में आपके कोड में संकलित नहीं किया जाएगा , इसलिए यह आमतौर पर विकास के लिए स्वच्छता की जाँच के लिए उपयोग किया जाता है।

यदि आप नहीं जोड़ते हैं तो वास्तव में, NSAssert आपके कोड में संकलित किया जाएगाNS_BLOCK_ASSERTIONS उपसर्ग फ़ाइलों में ।

तकनीकी नोट TN2190 में हम पा सकते हैं:

NDEBUG की तरह मैक्रोज़, फाउंडेशन की NSAssert को बंद करने के लिए C मुखर या NS_BLOCK_ASSERTIONS को बंद करने के लिए, आपकी पूर्वनिर्धारित उपसर्ग फ़ाइलों के लिए निर्दिष्ट करना महत्वपूर्ण है

या आप इसे पढ़ सकते हैं: कैसे पता चलेगा कि रिलीज़ बिल्ड में NSAssert अक्षम है या नहीं?


1

सामान्य तौर पर, प्रोग्रामर त्रुटियों को इंगित करने के लिए अपवादों का उपयोग किया जाता है - वे चीजें हैं जो नहीं होनी चाहिए। त्रुटियों का उपयोग त्रुटि स्थितियों को इंगित करने के लिए किया जाता है जो कार्यक्रम के सामान्य संचालन में आ सकते हैं - उपयोगकर्ता की त्रुटियां, मूल रूप से, या बाहरी परिस्थितियां जो सच होने की आवश्यकता होती हैं, लेकिन हो नहीं सकती हैं। इसलिए दस्तावेज़ में कुछ बंद तत्व को हटाने की कोशिश करना एक त्रुटि हो सकती है, और इंटरनेट कनेक्शन के बिना एक फ़ाइल डाउनलोड करने की कोशिश करना एक त्रुटि होगी, लेकिन एक संग्रह में एक अमान्य तत्व तक पहुंचने की कोशिश करना एक अपवाद होगा।

आम तौर पर परीक्षण में उपयोग किया जाता है, और AFAIK दूसरों की तरह एक सामान्य त्रुटि-हैंडलिंग तंत्र के रूप में उपयोग नहीं किया जाता है।


आक्रमणकारियों का इस्तेमाल हमलावरों को लागू करने के लिए किया जा सकता है। उदाहरण के लिए, NSParameterAssert(someParam != nil);अपरिवर्तनीय लागू करेगा कि निर्दिष्ट पैरामीटर शून्य नहीं होना चाहिए।
लिली बॉलर

@ केविन बैलार्ड: दावे आम तौर पर रिलीज बिल्ड से परिभाषित किए जाते हैं, या कम से कम वे आखिरी बार मुझे चेक किए गए थे, इसलिए जैसे मैंने कहा कि वे सामान्य त्रुटि-हैंडलिंग तंत्र नहीं हैं।
चक

1
वे हो सकते हैं, लेकिन वे डिफ़ॉल्ट रूप से छोड़ा नहीं गया है। आपको उस व्यवहार को प्राप्त करने के लिए एक बिल्ड सेटिंग को बदलना होगा।
लिली बॉलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.